diff --git a/.changeset/breezy-wasps-sparkle.md b/.changeset/breezy-wasps-sparkle.md new file mode 100644 index 0000000000..8072bf2e65 --- /dev/null +++ b/.changeset/breezy-wasps-sparkle.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed a bug in the built-in Jest configuration that prevented it from identifying packages that had migrated to using the new package scripts to run tests. diff --git a/.changeset/bright-nails-grin.md b/.changeset/bright-nails-grin.md deleted file mode 100644 index 434a17efbb..0000000000 --- a/.changeset/bright-nails-grin.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -'@backstage/backend-common': patch -'@backstage/catalog-client': patch -'@backstage/cli': patch -'@backstage/config-loader': patch -'@backstage/core-app-api': patch -'@backstage/core-components': patch -'@backstage/core-plugin-api': patch -'@backstage/errors': patch -'@backstage/integration': patch -'@backstage/integration-react': patch -'@backstage/release-manifests': patch -'@backstage/test-utils': patch -'@backstage/plugin-airbrake': patch -'@backstage/plugin-allure': patch -'@backstage/plugin-analytics-module-ga': patch -'@backstage/plugin-apache-airflow': patch -'@backstage/plugin-api-docs': patch -'@backstage/plugin-auth-backend': patch -'@backstage/plugin-auth-node': patch -'@backstage/plugin-azure-devops': patch -'@backstage/plugin-badges': patch -'@backstage/plugin-bazaar': patch -'@backstage/plugin-bitrise': patch -'@backstage/plugin-catalog': patch -'@backstage/plugin-catalog-backend': patch -'@backstage/plugin-catalog-backend-module-msgraph': patch -'@backstage/plugin-catalog-graphql': patch -'@backstage/plugin-catalog-import': patch -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-circleci': patch -'@backstage/plugin-cloudbuild': patch -'@backstage/plugin-code-coverage': patch -'@backstage/plugin-config-schema': patch -'@backstage/plugin-cost-insights': patch -'@backstage/plugin-explore': patch -'@backstage/plugin-explore-react': patch -'@backstage/plugin-firehydrant': patch -'@backstage/plugin-fossa': patch -'@backstage/plugin-gcp-projects': patch -'@backstage/plugin-git-release-manager': patch -'@backstage/plugin-github-actions': patch -'@backstage/plugin-github-deployments': patch -'@backstage/plugin-gitops-profiles': patch -'@backstage/plugin-gocd': patch -'@backstage/plugin-graphiql': patch -'@backstage/plugin-home': patch -'@backstage/plugin-ilert': patch -'@backstage/plugin-jenkins': patch -'@backstage/plugin-kafka': patch -'@backstage/plugin-kubernetes': patch -'@backstage/plugin-lighthouse': patch -'@backstage/plugin-newrelic': patch -'@backstage/plugin-newrelic-dashboard': patch -'@backstage/plugin-org': patch -'@backstage/plugin-pagerduty': patch -'@backstage/plugin-permission-backend': patch -'@backstage/plugin-permission-common': patch -'@backstage/plugin-permission-react': patch -'@backstage/plugin-rollbar': patch -'@backstage/plugin-rollbar-backend': patch -'@backstage/plugin-scaffolder': patch -'@backstage/plugin-scaffolder-backend': patch -'@backstage/plugin-search': patch -'@backstage/plugin-sentry': patch -'@backstage/plugin-shortcuts': patch -'@backstage/plugin-sonarqube': patch -'@backstage/plugin-splunk-on-call': patch -'@backstage/plugin-tech-insights': patch -'@backstage/plugin-tech-radar': patch -'@backstage/plugin-techdocs': patch -'@backstage/plugin-techdocs-backend': patch -'@backstage/plugin-todo': patch -'@backstage/plugin-user-settings': patch -'@backstage/plugin-xcmetrics': patch ---- - -Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 diff --git a/.changeset/chilled-glasses-tan.md b/.changeset/chilled-glasses-tan.md new file mode 100644 index 0000000000..e365d12ed8 --- /dev/null +++ b/.changeset/chilled-glasses-tan.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Deprecated the `runPeriodically` function which is no longer in use. diff --git a/.changeset/cold-ravens-grin.md b/.changeset/cold-ravens-grin.md new file mode 100644 index 0000000000..5ca43809ea --- /dev/null +++ b/.changeset/cold-ravens-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +The `CodeOwnersProcessor` no longer supports the deprecated SCM-specific location types like `'github/api'`. This is a breaking change but it is unlikely to have an impact, as these location types haven't been supported by the rest of the catalog for a long time. diff --git a/.changeset/cool-ways-battle.md b/.changeset/cool-ways-battle.md new file mode 100644 index 0000000000..383e2879c0 --- /dev/null +++ b/.changeset/cool-ways-battle.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-scaffolder-common': patch +--- + +**DEPRECATED** - The `TaskSpec.metadata` and `TaskSpec.baseUrl` has been deprecated in favour of the new `TaskSpec.templateInfo`. +The `baseUrl` is now found on the `templateInfo` object, and the name can be inferred from the `templateInfo.entityRef` property. + +Usages of `TaskSpec.metadata.name` or `ctx.metadata.name` in Actions should migrate to using `parseEntityRef(taskSpec.templateInfo.entityRef)` to get the parsed entity triplet. + +Usages of `ctx.baseUrl` in Actions should migrate to using `ctx.templateInfo.baseUrl` instead. diff --git a/.changeset/dependabot-5625654.md b/.changeset/dependabot-5625654.md new file mode 100644 index 0000000000..b61e198d24 --- /dev/null +++ b/.changeset/dependabot-5625654.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +chore(deps-dev): bump `@types/rollup-plugin-postcss` from 2.0.1 to 3.1.4 diff --git a/.changeset/dependabot-ff26237.md b/.changeset/dependabot-ff26237.md new file mode 100644 index 0000000000..e390ef12b5 --- /dev/null +++ b/.changeset/dependabot-ff26237.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +chore(deps): bump `@hot-loader/react-dom` from 16.13.0 to 17.0.2 diff --git a/.changeset/dry-papayas-melt.md b/.changeset/dry-papayas-melt.md new file mode 100644 index 0000000000..255b2cbc85 --- /dev/null +++ b/.changeset/dry-papayas-melt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Renamed `CatalogResultListItem` to `CatalogSearchResultListItem` along with its prop type, leaving the old names in place as a deprecations. diff --git a/.changeset/dry-ties-collect.md b/.changeset/dry-ties-collect.md new file mode 100644 index 0000000000..9ad3afb208 --- /dev/null +++ b/.changeset/dry-ties-collect.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Added an `/entity-facets` endpoint, which lets you query the distribution of +possible values for fields of entities. + +This can be useful for example when populating a dropdown in the user interface, +such as listing all tag values that are actually being used right now in your +catalog instance, along with putting the most common ones at the top. diff --git a/.changeset/dull-windows-carry.md b/.changeset/dull-windows-carry.md new file mode 100644 index 0000000000..fb259f1e56 --- /dev/null +++ b/.changeset/dull-windows-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +**BREAKING**: Removed unused `durationText` utility. diff --git a/.changeset/eleven-turkeys-behave.md b/.changeset/eleven-turkeys-behave.md new file mode 100644 index 0000000000..f9c5cbf201 --- /dev/null +++ b/.changeset/eleven-turkeys-behave.md @@ -0,0 +1,33 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +**BREAKING**: Removed `AwsOrganizationCloudAccountProcessor` from the default +set of builtin processors, and instead moved it into its own module +`@backstage/plugin-catalog-backend-module-aws`. + +If you were using this processor, through making use of the location type +`aws-cloud-accounts` and/or using the configuration key +`catalog.processors.awsOrganization`, you will from now on have to add the +processor manually to your catalog. + +First, add the `@backstage/plugin-catalog-backend-module-aws` dependency to your +`packages/backend` package. + +Then, in `packages/backend/src/plugins/catalog.ts`: + +```diff ++import { AwsOrganizationCloudAccountProcessor } from '@backstage/plugin-catalog-backend-module-aws'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const builder = await CatalogBuilder.create(env); ++ builder.addProcessor( ++ AwsOrganizationCloudAccountProcessor.fromConfig( ++ env.config, ++ { logger: env.logger } ++ ) ++ ); + // ... +``` diff --git a/.changeset/fast-ducks-sell.md b/.changeset/fast-ducks-sell.md deleted file mode 100644 index 2ad654124d..0000000000 --- a/.changeset/fast-ducks-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Support "dependencyOf" relation in Resource entities diff --git a/.changeset/five-apes-rest.md b/.changeset/five-apes-rest.md new file mode 100644 index 0000000000..d4704d2014 --- /dev/null +++ b/.changeset/five-apes-rest.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Added `EntitySwitchProps` type for `EntitySwitch`. diff --git a/.changeset/gentle-buttons-hunt.md b/.changeset/gentle-buttons-hunt.md new file mode 100644 index 0000000000..677e8f4e85 --- /dev/null +++ b/.changeset/gentle-buttons-hunt.md @@ -0,0 +1,22 @@ +--- +'@backstage/create-app': patch +--- + +Update the template to reflect the renaming of `CatalogResultListItem` to `CatalogSearchResultListItem` from `@backstage/plugin-catalog`. + +To apply this change to an existing app, make the following change to `packages/app/src/components/search/SearchPage.tsx`: + +```diff +-import { CatalogResultListItem } from '@backstage/plugin-catalog'; ++import { CatalogSearchResultListItem } from '@backstage/plugin-catalog'; +``` + +```diff + case 'software-catalog': + return ( +- +``` diff --git a/.changeset/gentle-ghosts-love.md b/.changeset/gentle-ghosts-love.md new file mode 100644 index 0000000000..34efebad84 --- /dev/null +++ b/.changeset/gentle-ghosts-love.md @@ -0,0 +1,19 @@ +--- +'@backstage/plugin-scaffolder-backend': minor +--- + +- **BREAKING** - `DatabaseTaskStore()` constructor is now removed. Please use the `DatabaseTaskStore.create()` method instead. + +- **BREAKING** - `TaskStore.createTask()` method now only takes one argument of type `TaskStoreCreateTaskOptions` which encapsulates the `spec` and `secrets` + +```diff +- TaskStore.createTask(spec, secrets) ++ TaskStore.createTask({ spec, secrets}) +``` + +- **BREAKING** - `TaskBroker.dispatch()` method now only takes one argument of type `TaskBrokerDispatchOptions` which encapsulates the `spec` and `secrets` + +```diff +- TaskBroker.dispatch(spec, secrets) ++ TaskBroker.dispatch({ spec, secrets}) +``` diff --git a/.changeset/grumpy-eels-swim.md b/.changeset/grumpy-eels-swim.md new file mode 100644 index 0000000000..bbf5b1ca79 --- /dev/null +++ b/.changeset/grumpy-eels-swim.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Allow missing kubernetes config in development env diff --git a/.changeset/grumpy-grapes-type.md b/.changeset/grumpy-grapes-type.md new file mode 100644 index 0000000000..cd1e9f4430 --- /dev/null +++ b/.changeset/grumpy-grapes-type.md @@ -0,0 +1,23 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Deprecated the second parameter of `results.location()` that determines whether an emitted location is optional. In cases where this is currently being set to `false`, the parameter can simply be dropped, as that is the default. Usage where this was being set to `true` should be migrated to set the `presence` option of the emitted location to `optional`. For example: + +```ts +results.location( + { + type: 'url', + target: 'http://example.com/foo', + }, + true, +); + +// migrated to + +results.location({ + type: 'url', + target: 'http://example.com/foo', + presence: 'optional', +}); +``` diff --git a/.changeset/honest-apples-notice.md b/.changeset/honest-apples-notice.md new file mode 100644 index 0000000000..da517b95a7 --- /dev/null +++ b/.changeset/honest-apples-notice.md @@ -0,0 +1,18 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +**BREAKING**: The default sign-in resolvers for all providers, if you choose to +use them, now emit the token `sub` and `ent` claims on the standard, +all-lowercase form, instead of the mixed-case form. The mixed-case form causes +problems for implementations that naively do string comparisons on refs. The end +result is that you may for example see your Backstage token `sub` claim now +become `'user:default/my-id'` instead of `'user:default/My-ID'`. + +On a related note, specifically the SAML provider now correctly issues both +`sub` and `ent` claims, and on the full entity ref form instead of the short +form with only the ID. + +**NOTE**: For a long time, it has been strongly recommended that you provide +your own sign-in resolver instead of using the builtin ones, and that will +become mandatory in the future. diff --git a/.changeset/large-baboons-wash.md b/.changeset/large-baboons-wash.md new file mode 100644 index 0000000000..67204bb13c --- /dev/null +++ b/.changeset/large-baboons-wash.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +Improved API documentation. + +**BREAKING**: The individual table column factories (e.g. `createEntityRefColumn`) are now no longer available directly, but only through `EntityTable.columns`. diff --git a/.changeset/lovely-chairs-confess.md b/.changeset/lovely-chairs-confess.md new file mode 100644 index 0000000000..5c785e89d2 --- /dev/null +++ b/.changeset/lovely-chairs-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Added `EntityRelationSpec`, which was moved over from `@backstage/catalog-model`. diff --git a/.changeset/lovely-falcons-hang.md b/.changeset/lovely-falcons-hang.md new file mode 100644 index 0000000000..5a849f11f5 --- /dev/null +++ b/.changeset/lovely-falcons-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': minor +--- + +**BREAKING**: Removed `EntityRelationSpec` as it is only used during the catalog during the catalog processing. diff --git a/.changeset/lucky-bulldogs-own.md b/.changeset/lucky-bulldogs-own.md new file mode 100644 index 0000000000..4fb27d90b4 --- /dev/null +++ b/.changeset/lucky-bulldogs-own.md @@ -0,0 +1,15 @@ +--- +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-badges-backend': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-todo-backend': patch +--- + +Updated according to the new `getEntityFacets` catalog API method diff --git a/.changeset/old-schools-walk.md b/.changeset/old-schools-walk.md new file mode 100644 index 0000000000..7ed7e070af --- /dev/null +++ b/.changeset/old-schools-walk.md @@ -0,0 +1,33 @@ +--- +'@backstage/plugin-catalog-backend-module-aws': minor +--- + +Added this new catalog module, initially containing only the +`AwsOrganizationCloudAccountProcessor`. + +Note that this was moved over from the catalog backend itself, and therefore is +no longer part of its builtin set of processors. If you were using this +processor, through making use of the location type `aws-cloud-accounts` and/or +using the configuration key `catalog.processors.awsOrganization`, you will from +now on have to add the processor manually to your catalog. + +First, add the `@backstage/plugin-catalog-backend-module-aws` dependency to your +`packages/backend` package. + +Then, in `packages/backend/src/plugins/catalog.ts`: + +```diff ++import { AwsOrganizationCloudAccountProcessor } from '@backstage/plugin-catalog-backend-module-aws'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const builder = await CatalogBuilder.create(env); ++ builder.addProcessor( ++ AwsOrganizationCloudAccountProcessor.fromConfig( ++ env.config, ++ { logger: env.logger } ++ ) ++ ); + // ... +``` diff --git a/.changeset/patched.json b/.changeset/patched.json index 1029c8f106..594b6b01af 100644 --- a/.changeset/patched.json +++ b/.changeset/patched.json @@ -1,3 +1,50 @@ { - "currentReleaseVersion": {} + "currentReleaseVersion": { + "@backstage/backend-common": "0.10.9", + "@backstage/backend-tasks": "0.1.8", + "@backstage/catalog-client": "0.7.1", + "@backstage/catalog-model": "0.10.1", + "@backstage/cli-common": "0.1.8", + "@backstage/config": "0.1.15", + "@backstage/config-loader": "0.9.5", + "@backstage/errors": "0.2.2", + "@backstage/integration": "0.7.4", + "@backstage/search-common": "0.2.4", + "@backstage/techdocs-common": "0.11.9", + "@backstage/types": "0.1.3", + "@backstage/plugin-app-backend": "0.3.26", + "@backstage/plugin-auth-backend": "0.10.2", + "@backstage/plugin-auth-node": "0.1.2", + "@backstage/plugin-azure-devops-backend": "0.3.5", + "@backstage/plugin-azure-devops-common": "0.2.2", + "@backstage/plugin-badges-backend": "0.1.20", + "@backstage/plugin-catalog-backend": "0.21.5", + "@backstage/plugin-catalog-common": "0.1.4", + "@backstage/plugin-catalog-graphql": "0.3.3", + "@backstage/plugin-code-coverage-backend": "0.1.24", + "@backstage/plugin-graphql-backend": "0.1.16", + "@backstage/plugin-jenkins-backend": "0.1.15", + "@backstage/plugin-kafka-backend": "0.2.19", + "@backstage/plugin-kubernetes-backend": "0.4.9", + "@backstage/plugin-kubernetes-common": "0.2.4", + "@backstage/plugin-permission-backend": "0.5.1", + "@backstage/plugin-permission-common": "0.5.1", + "@backstage/plugin-permission-node": "0.5.1", + "@backstage/plugin-proxy-backend": "0.2.20", + "@backstage/plugin-rollbar-backend": "0.1.23", + "@backstage/plugin-scaffolder-backend": "0.16.1", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.1", + "@backstage/plugin-scaffolder-backend-module-rails": "0.3.1", + "@backstage/plugin-scaffolder-common": "0.2.1", + "@backstage/plugin-search-backend": "0.4.4", + "@backstage/plugin-search-backend-module-elasticsearch": "0.0.10", + "@backstage/plugin-search-backend-module-pg": "0.2.8", + "@backstage/plugin-search-backend-node": "0.4.7", + "@backstage/plugin-tech-insights-backend": "0.2.6", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.10", + "@backstage/plugin-tech-insights-common": "0.2.3", + "@backstage/plugin-tech-insights-node": "0.2.4", + "@backstage/plugin-techdocs-backend": "0.13.5", + "@backstage/plugin-todo-backend": "0.1.23" + } } diff --git a/.changeset/pink-fans-tie.md b/.changeset/pink-fans-tie.md new file mode 100644 index 0000000000..713a7f9b50 --- /dev/null +++ b/.changeset/pink-fans-tie.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Include any files included in configuration via $include or $file directives when watching for configuration changes. diff --git a/.changeset/poor-tomatoes-stare.md b/.changeset/poor-tomatoes-stare.md new file mode 100644 index 0000000000..5e45316784 --- /dev/null +++ b/.changeset/poor-tomatoes-stare.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Deprecated `StaticLocationProcessor` which is unused and replaced by `ConfigLocationEntityProvider`. diff --git a/.changeset/purple-camels-accept.md b/.changeset/purple-camels-accept.md new file mode 100644 index 0000000000..fe3da66a74 --- /dev/null +++ b/.changeset/purple-camels-accept.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +'@backstage/plugin-scaffolder-backend-module-rails': patch +--- + +Migrated over from the deprecated `spec.metadata` to `spec.templateInfo` for the `name` and the `baseUrl` of the template. diff --git a/.changeset/quiet-waves-film.md b/.changeset/quiet-waves-film.md new file mode 100644 index 0000000000..206cef6287 --- /dev/null +++ b/.changeset/quiet-waves-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-deployments': patch +--- + +The removed `'github'` catalog location type no longer triggers a GitHub integration configuration lookup. diff --git a/.changeset/rare-moles-play.md b/.changeset/rare-moles-play.md new file mode 100644 index 0000000000..26fe7cd9b0 --- /dev/null +++ b/.changeset/rare-moles-play.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-api-docs': minor +'@backstage/plugin-catalog': minor +'@backstage/plugin-circleci': minor +'@backstage/plugin-cloudbuild': minor +'@backstage/plugin-github-actions': minor +'@backstage/plugin-jenkins': minor +'@backstage/plugin-kafka': minor +'@backstage/plugin-kubernetes': minor +'@backstage/plugin-lighthouse': minor +'@backstage/plugin-org': minor +'@backstage/plugin-rollbar': minor +'@backstage/plugin-sonarqube': minor +'@backstage/plugin-techdocs': minor +--- + +**BREAKING**: Removed support for passing in an explicit `entity` prop to entity page extensions, which has been deprecated for a long time. This is only a breaking change at the TypeScript level, as this property was already ignored. diff --git a/.changeset/red-olives-clap.md b/.changeset/red-olives-clap.md new file mode 100644 index 0000000000..ac8ac1cda6 --- /dev/null +++ b/.changeset/red-olives-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Made the `GitLabDiscoveryProcessor.updateLastActivity` method private, as it was accidentally exposed. It has also been fixed to properly operate in its own cache namespace to avoid collisions with other processors. diff --git a/.changeset/silent-kiwis-allow.md b/.changeset/silent-kiwis-allow.md new file mode 100644 index 0000000000..cfe5e9d1b7 --- /dev/null +++ b/.changeset/silent-kiwis-allow.md @@ -0,0 +1,6 @@ +--- +'@techdocs/cli': patch +'@backstage/techdocs-common': patch +--- + +Updated usage of `github:` location types in docs to use `url:` instead. diff --git a/.changeset/spicy-cherries-ring.md b/.changeset/spicy-cherries-ring.md new file mode 100644 index 0000000000..af6fcacd90 --- /dev/null +++ b/.changeset/spicy-cherries-ring.md @@ -0,0 +1,19 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Updated all processors to implement `getProcessorName`. + +**BREAKING**: The `CatalogProcessor` interface now require that the `CatalogProcessor` class implements `getProcessorName()`. +The processor name has previously defaulted processor class name. It's therefore _recommended_ to keep your return the same name as the class name if you did not implement this method previously. + +For example: + +```ts +class CustomProcessor implements CatalogProcessor { + getProcessorName() { + // Use the same name as the class name if this method was not previously implemented. + return 'CustomProcessor'; + } +} +``` diff --git a/.changeset/stupid-years-speak.md b/.changeset/stupid-years-speak.md new file mode 100644 index 0000000000..cd454087b2 --- /dev/null +++ b/.changeset/stupid-years-speak.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Minor wording update diff --git a/.changeset/tender-apricots-fetch.md b/.changeset/tender-apricots-fetch.md new file mode 100644 index 0000000000..5fe8bda4ef --- /dev/null +++ b/.changeset/tender-apricots-fetch.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +- **DEPRECATED** - `Status` has been deprecated in favour of `TaskStatus` +- **DEPRECATED** - `CompletedTaskState` has been deprecated in favour of `TaskCompletionState` +- **DEPRECATED** - `DispatchResult` has been deprecated in favour of `TaskBrokerDispatchResult` diff --git a/.changeset/thick-tools-tan.md b/.changeset/thick-tools-tan.md new file mode 100644 index 0000000000..19c63f53fe --- /dev/null +++ b/.changeset/thick-tools-tan.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': minor +--- + +**BREAKING**: Removed the old `plugin` export, use `catalogPlugin` instead. diff --git a/.changeset/thirty-peas-exist.md b/.changeset/thirty-peas-exist.md new file mode 100644 index 0000000000..7c71d1047f --- /dev/null +++ b/.changeset/thirty-peas-exist.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Fixed bug in integration package where Self Hosted GitLab instances with custom ports weren't supported (because of the lack of an option to add the port in the integration configs. Now users can add the port directly in the host) diff --git a/.changeset/tiny-ads-knock.md b/.changeset/tiny-ads-knock.md new file mode 100644 index 0000000000..ba24ad6906 --- /dev/null +++ b/.changeset/tiny-ads-knock.md @@ -0,0 +1,8 @@ +--- +'@backstage/catalog-client': patch +--- + +Added `CatalogApi.getEntityFacets`. Marking this as a breaking change since it +is a non-optional addition to the API and depends on the backend being in place. +If you are mocking this interface in your tests, you will need to add an extra +`getEntityFacets: jest.fn()` or similar to that interface. diff --git a/.changeset/unlucky-penguins-wonder.md b/.changeset/unlucky-penguins-wonder.md new file mode 100644 index 0000000000..f5c5e5af3a --- /dev/null +++ b/.changeset/unlucky-penguins-wonder.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Implemented required `getProcessorName` method for catalog processor. diff --git a/.changeset/young-guests-confess.md b/.changeset/young-guests-confess.md new file mode 100644 index 0000000000..c27c99c147 --- /dev/null +++ b/.changeset/young-guests-confess.md @@ -0,0 +1,28 @@ +--- +'@backstage/create-app': patch +--- + +To reflect the updated `knex` and `@vscode/sqlite3` dependencies introduced with [v0.4.19](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md#0419), we update our example `Dockerfile`, adding `@vscode/sqlite3` build dependencies to the image. Further on, we updated it to the `node:16-bullseye-slim` base image. + +To apply this update to an existing app, make the following change to `packages/backend/Dockerfile`: + +```diff +-FROM node:14-buster-slim ++FROM node:16-bullseye-slim +``` + +and, _only if you are using sqlite3 in your app_: + +```diff +RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz ++ ++# install sqlite3 dependencies ++RUN apt-get update && \ ++ apt-get install -y libsqlite3-dev python3 cmake g++ && \ ++ rm -rf /var/lib/apt/lists/* && \ ++ yarn config set python /usr/bin/python3 + +RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" +``` + +If you are using a multi-stage Docker build for your app, please refer to the [updated examples](https://github.com/backstage/backstage/blob/master/docs/deployment/docker.md#multi-stage-build) in the documentation. diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 8303510e77..408b84903c 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -17,6 +17,7 @@ autoscaling Autoscaling autoselect Avro +aws backrub backported backporting diff --git a/.github/workflows/automate_techdocs-project-board.yml b/.github/workflows/automate_techdocs-project-board.yml deleted file mode 100644 index f551412f95..0000000000 --- a/.github/workflows/automate_techdocs-project-board.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Automate TechDocs project board -# Development of TechDocs in Backstage is managed by this Kanban board - https://github.com/orgs/backstage/projects/1 -# New issues and PRs with TechDocs in their title or docs-like-code label will be added to the board. -# Caveat: New PRs created from forks will not be added since GitHub Actions don't share credentials with forks. - -on: - issues: - types: [opened, reopened, labeled, edited] - pull_request: - types: [opened, reopened, labeled, edited] - -jobs: - assign_issue_or_pr_to_project: - runs-on: ubuntu-latest - name: Triage - env: - MY_GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - steps: - - name: Assign new issue to Incoming based on its title. - uses: srggrs/assign-one-project-github-action@1.2.0 - if: | - env.MY_GITHUB_TOKEN != null && - contains(github.event.issue.title, 'TechDocs') || - contains(github.event.issue.title, 'techdocs') || - contains(github.event.issue.title, 'Techdocs') - with: - project: 'https://github.com/orgs/backstage/projects/1' - column_name: 'Incoming' - - - name: Assign new issue to Incoming based on its label. - uses: srggrs/assign-one-project-github-action@1.2.0 - if: | - env.MY_GITHUB_TOKEN != null && - contains(github.event.issue.labels.*.name, 'docs-like-code') - with: - project: 'https://github.com/orgs/backstage/projects/1' - column_name: 'Incoming' - - - name: Assign new PR to Incoming based on its title. - uses: srggrs/assign-one-project-github-action@1.2.0 - if: | - env.MY_GITHUB_TOKEN != null && - contains(github.event.pull_request.title, 'TechDocs') || - contains(github.event.pull_request.title, 'techdocs') || - contains(github.event.pull_request.title, 'Techdocs') - with: - project: 'https://github.com/orgs/backstage/projects/1' - column_name: 'Incoming' - - - name: Assign new PR to Incoming based on its label. - uses: srggrs/assign-one-project-github-action@1.2.0 - if: | - env.MY_GITHUB_TOKEN != null && - contains(github.event.pull_request.labels.*.name, 'docs-like-code') - with: - project: 'https://github.com/orgs/backstage/projects/1' - column_name: 'Incoming' diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index ed02a313fe..32e3542029 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -189,7 +189,7 @@ jobs: run: yarn tsc:full - name: build packages - run: yarn lerna -- run --ignore example-app build + run: yarn lerna -- run --ignore example-app --ignore example-backend build # Publishes current version of packages that are not already present in the registry - name: publish diff --git a/ADOPTERS.md b/ADOPTERS.md index beb161d9ee..772651d54c 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -1,94 +1,96 @@ -| Organization | Contact | Description of Use | -| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | -| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. | -| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | -| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | -| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. | -| [SDA SE](https://sda.se) | [@dschwank](https://github.com/dschwank), [@iammnils](https://github.com/iammnils) | Central place for developing and sharing services in our insurance ecosystem. | -| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. | -| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications | -| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. | -| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | -| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D | -| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling | -| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling | -| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks | -| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. | -| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. | -| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. | -| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit | -| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go | -| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling | -| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. | -| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. | -| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. | -| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. | -| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. | -| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. | -| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. | -| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. | -| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. | -| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. | -| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process πŸŒ•πŸš€πŸ§‘β€πŸš€ | -| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | -| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | -| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | -| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | -| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | -| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. | -| [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. | -| [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. | -| [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. | -| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | -| [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration | -| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. | -| [2U](https://2u.com) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar | -| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. | -| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. | -| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. | -| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. | -| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc | -| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. | -| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | -| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | -| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. | -| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. | -| [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systemsπŸš€. | -| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | -| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. | -| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. | -| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. | -| [Adevinta](https://www.adevinta.com) | [Ray Sinnema](https://github.com/RemonSinnema) | Showcase shared services to our internal customers. | -| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation. | -| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc. | -| [Volvofinans Bank](https://www.volvofinans.se) | [Johan Hammar](https://github.com/johanhammar) | Developer portal enabling engineers to manage and explore software and documentation. | -| [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling | -| [Signal Iduna Group](https://www.signal-iduna.de/) | [Jonas Thomsen](https://github.com/JoThomsen) | Developer Portal, documentation, monitoring, service catalog for our insurance ecosystem | -| [Tradeshift](https://www.tradeshift.com/) | [Soren Mathiasen](https://github.com/sorenmat) | Developer Portal: documentation, monitoring, service templates, service catalog for our micro services | -| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | -| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | -| [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | -| [Globo](https://globo.com) | [Carlos GusmΓ£o](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | -| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly πŸš€ | -| [GoTo](https://www.goto.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. | -| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates
Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc | -| [Mosaico](https://www.mosaico.com.br/) | [WΓ©dney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. | -| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon), [Gauthier Roebroeck](https://github.com/gauthier-roebroeck-mox) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong πŸ₯°πŸš€ | -| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. πŸš— | -| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. | -| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding | -| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. | -| [EF Education First](https://www.ef.com) | [Daan Boerlage](https://github.com/runebaas), [RafaΕ‚ Nowosielski](https://github.com/rnowosielski) | Our developer portal - primarily used for cataloging and scaffolding with the ambition to expand with more feature adoptions over time | -| [Power Home Remodeling](https://www.techatpower.com) | [Ben Langfeld](https://github.com/benlangfeld) | Developer portal to our internal services, build on open-source software (including Kubernetes) in our own datacenters. Our Portal allows our team members to navigate inherant complexity and standardise. | -| [Livspace](https://www.livspace.com) | [Praveen Kumar](https://github.com/praveen-livspace) | Developer portal, service catalog, tech docs, API docs and plugins | -| [Just Eat Takeaway](https://www.justeattakeaway.com) | [Kim Wilson](https://github.com/kwilson541) | Our developer portal which centralises applications, reduces cognitive load and provides teams insights. | -| [Hopin](https://hopin.com) | [Vladimir Glafirov](https://github.com/vglafirov), [Chloe Lee](https://github.com/msfuko) | Developer portal to streamline the development practices. Integrated with service catalog, software templates, application monitoring, tech docs and plugins. | -| [HBO Max](https://hbomax.com) | [@mdb](https://github.com/mdb), [@nesta219](https://github.com/nesta219), [@nmische](https://github.com/nmische), [@hbomark](https://github.com/hbomark) | Developer portal hosting service catalog and API documentation, as well as cloud infrastructure details, operational visibility tools, and a custom plugin for browsing notable platform change events, such as deployments and configuration updates. | -| [RCHLO](https://www.riachuelo.com.br) & [MIDWAY](https://www.midway.com.br) | [@marcosborges](https://github.com/marcosborges), [@defaultbr](https://github.com/defaultbr) | Self-Service Platform | -| [HP Inc](https://www.hp.com) | [Damon Kaswell](https://github.com/dekoding) | DevEx engagement hub (dev portal: docs, standards, Q&A) and extensive assets catalog (APIs, services, code, data, etc.) for the pan-HP internal developer community. -| [VMware](https://www.vmware.com) | [@mpriamo](https://github.com/mpriamo), [@krisapplegate](https://github.com/krisapplegate) | Part of [Tanzu Application Platform](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) offering; internal developer portal | -| [UalΓ‘](https://www.uala.com.ar/) | [Santiago Bernal](https://github.com/sabernal) | Initial work being done to centralize documentation for all our microservices and APIs, as well as scaffolding new services and tracking code quality | -| [IKEA IT AB](https://www.ingka.com) | [@bjornramberg](https://github.com/bjornramberg), [@supriyachitale](https://github.com/supriyachitale) | Supporting engineers at scale with self serve access and connecting the dots of our engineering platform and services, enabling product teams to move faster and go further, and unleashing innovation, reuse and co-creation across the organisation. | -| [Invitae](https://www.invitae.com/en) | [@ryan-hanchett](https://github.com/ryan-hanchett), [@gmandler42](https://github.com/gmandler42) | Centralized Developer Experience portal, putting all of our tooling behind a single pane of glass and creating a living service catalog. | -| [Fortum](https://www.fortum.com/) | [@brunoamaroalmeida](https://github.com/brunoamaroalmeida), [@dhaval-vithalani](https://github.com/dhaval-vithalani), [@sunilkumarmohanty](https://github.com/sunilkumarmohanty) | A central portal containing information about our applications, services, processes and other software assets to be used by Fortum software engineering community. | +| Organization | Contact | Description of Use | +| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | +| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. | +| [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | +| [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | +| [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. | +| [SDA SE](https://sda.se) | [@dschwank](https://github.com/dschwank), [@iammnils](https://github.com/iammnils) | Central place for developing and sharing services in our insurance ecosystem. | +| [H-E-B](https://www.heb.com) | [@german-j-rodriguez](https://github.com/german-j-rodriguez) | Initial work on Engineering Portal service platform. | +| [American Airlines](https://www.aa.com) | [@paulpach](https://github.com/paulpach) | Central place for developers to develop and maintain applications | +| [Kiwi.com](https://kiwi.com) | [@aexvir](https://github.com/aexvir) | Replacing the frontend of [The Zoo](https://github.com/kiwicom/the-zoo), their service registry. | +| [Voi](https://www.voiscooters.com/) | [@K-Phoen](https://github.com/K-Phoen) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | +| [Talkdesk](https://www.talkdesk.com) | [@jaime-talkdesk](https://github.com/jaime-talkdesk) | Initial work for Engineering Portal and Self Provisioning to R&D | +| [Wealthsimple](https://www.wealthsimple.com) | [@andrewthauer](https://github.com/andrewthauer) | Developer portal, service catalog, documentation and tooling | +| [Grab](https://www.grab.com) | [@althafh](https://github.com/althafh) | Initial work as a unified interface for all of Grab's internal tooling | +| [Telenor Sweden](https://www.telenor.se) | [@O5ten](https://github.com/O5ten) | Building a developer portal for scaffolding projects towards our unified build environment and microservice stacks | +| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. | +| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. | +| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. | +| [Expedia Group](https://www.expediagroup.com) | [Mike Turner](mailto:miturner@expediagroup.com), [Sneha Kumar](mailto:snkumar@expediagroup.com), [@guillermomanzo](https://github.com/guillermomanzo), [Erik Lindgren](https://github.com/lindgren) | EG Common Developer Toolkit | +| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go | +| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling | +| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. | +| [Trendyol](https://trendyol.com) | [Gamze Senturk](https://github.com/gmzsenturk), [Mert Can Bilgic](https://github.com/mertcb) | The Developer Portal has been called `Pandora`. Provides an overview of Trendyol tech ecosystem. TechDocs, Catalog, Custom Plugins and Theme. | +| [Peloton](https://www.onepeloton.com/) | [Jim Haughwout](https://github.com/JimHaughwout) | Creating our first developer portal and tech-docs. Exploring Service Catalog, Tech Insights and Cost Insights as well. | +| [TELUS](https://telus.com) | [Seb Barre](https://github.com/sbarre) | The Go-to place to find answers about development and delivery at TELUS. | +| [Brex](https://www.brex.com/) | [Vamsi Chitters](https://github.com/vamsikc) | A centralized UI to understand how a service fits in the whole Brex architecture and manage a team’s engineering dependencies. | +| [Oriflame](https://www.oriflame.com/) | [Oriflame](https://github.com/oriflame) | Internal developer portal for services, single page apps and packages overview, API documentation, technical guides, tech-radar and more. | +| [Booz Allen Hamilton](https://www.boozallen.com/) | [Jason Miller](https://github.com/JasonMiller-BAH) | Developer portal for a full-stack software development ecosystem that accelerates consistent and repeatable Modern Software Development practices for internal innovation and investments. | +| [Netflix](https://www.netflix.com/) | [bleathem](https://github.com/bleathem) | Our Backstage implementation will be the front door to a unified experience connecting our internal platform products across important workflows with integrated knowledge and support. | +| [b.well](https://www.icanbwell.com/) | [Jacob Rosales](https://github.com/jrosales) | Foundation for our engineering portal and cloud insights. | +| [PagerDuty](https://www.pagerduty.com/) | [Mark Shaw](https://github.com/markshawtoronto) | Developer portal, initially focused on software templates and tech-docs. | +| [MoonShiner](https://moonshiner.at) | [Fabian Hippmann](https://github.com/FabianHippmann) | Developer portal - helps us keep track of our customer projects, onboard new developers & improve our development process πŸŒ•πŸš€πŸ§‘β€πŸš€ | +| [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | +| [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | +| [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | +| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | +| [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | +| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. | +| [MavTek](https://www.mavtek.com/) | [@fgascon](https://github.com/fgascon) | Developer portal focused on standardizing practices, centralizing documentation and streamlining developer practices. | +| [QuintoAndar](https://www.quintoandar.com.br/) | [@quintoandar](https://github.com/quintoandar) | Developer portal, services catalog and centralization of service metrics. | +| [empathy.co](https://empathy.co/) | [@guillermotti](https://github.com/guillermotti) | Developer portal for tech docs, service catalog, plugin discovery and much more. | +| [creditas.com](https://creditas.com/) | [@aureliosaraiva](https://github.com/aureliosaraiva) [@Creditas](https://github.com/creditas) | Centralization of all services, standards, documentation, etc. We started the deployment process. | +| [Prisjakt](https://www.prisjakt.nu) / [PriceSpy](https://pricespy.co.uk) | [@kennylindahl](https://github.com/kennylindahl) | Internal developer portal - Documentation, scaffolding, software catalog, TechRadar, Gitlab org data integration | +| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. | +| [2U](https://2u.com) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar | +| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. | +| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. | +| [Loadsmart](https://loadsmart.com/) | [Loadsmart](https://github.com/loadsmart) | Improve services visibility and operations for service owners and developers. | +| [Monzo](https://monzo.com/) | [@WillSewell](https://github.com/WillSewell), [@joechrisellis](https://github.com/joechrisellis) | Developer portal showing metadata and docs for over 2000 microservices. We have built a number of plugins such as a UI for our system to measure [software excellence](https://monzo.com/blog/2021/09/15/how-we-measure-software-excellence), and a UI to show deployment and config change events. | +| [Vaimo](https://www.vaimo.com) | [@vaimo-magnus](https://github.com/vaimo-magnus) | Developer Portal for our developers at Vaimo, currently docs and self-service towards our internal PaaS based on k8s. Plans to extend the catalog into Projects, Environments etc | +| [Wayfair](https://www.wayfair.com) | [@fransan](https://github.com/fransan), [@errskipower](https://github.com/errskipower), [@hrrs](https://github.com/hrrs) | Developer portal for service catalog, technical documentation, and APIs. | +| [CircleHD](https://www.circlehd.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | +| [CastDesk](https://castdesk.com) | [@circlehddev](https://github.com/circlehddev) | Developer Portal for internal dev team across the globe | +| [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. | +| [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. | +| [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systemsπŸš€. | +| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | +| [Box](https://www.box.com) | [@kielosz](https://github.com/kielosz), [@jluk-box](https://github.com/jluk-box), [@ptychu](https://github.com/ptychu), [@alexrybch](https://github.com/alexrybch), [@szubster](https://github.com/szubster) | Developer portal for service catalog, integration with internal systems, new service onboarding. | +| [Bazaarvoice](https://www.bazaarvoice.com) | [@niallmccullagh](https://github.com/niallmccullagh) | Developer portal for service catalog and scaffolds, publishing Github docs and API documentation, visualising our internal tech radar and our product engineering org structure. | +| [Krateo PlatformOps](https://www.krateo.io) | [@projectkerberus](https://github.com/projectkerberus) | A multi-cloud control plane to create, manage and deploy any kind of resource easily and centrally via a Developer Portal that centralizes via a self-service catalog the templating and ownership of services, the available documentation, the overview of the components that compose an entire domain and all the data of the service lifecycle. | +| [Adevinta](https://www.adevinta.com) | [Ray Sinnema](https://github.com/RemonSinnema) | Showcase shared services to our internal customers. | +| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation. | +| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc. | +| [Volvofinans Bank](https://www.volvofinans.se) | [Johan Hammar](https://github.com/johanhammar) | Developer portal enabling engineers to manage and explore software and documentation. | +| [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling | +| [Signal Iduna Group](https://www.signal-iduna.de/) | [Jonas Thomsen](https://github.com/JoThomsen) | Developer Portal, documentation, monitoring, service catalog for our insurance ecosystem | +| [Tradeshift](https://www.tradeshift.com/) | [Soren Mathiasen](https://github.com/sorenmat) | Developer Portal: documentation, monitoring, service templates, service catalog for our micro services | +| [Unity](https://unity.com) | [Ted Cordery](https://github.com/TeddyBallGame) | A centralized service catalog with documentation for our service engineers. | +| [PicPay](https://www.picpay.com) | [Luis Baroni](https://github.com/lcsbaroni), [Renata Poluceno](https://github.com/renatapoluceno), [PicPay](https://github.com/picpay) | Developer portal for building services throught templates, service catalog with ownership of services, documentation and metrics providing autonomy and visibility for all. | +| [Epic Games](https://www.epicgames.com) | [Brian Jung](https://github.com/brian-at-epic), [Jeff Goldian](https://github.com/jeffgoldian-Epic) | Developer Portal: Service Catalog, Documentation, Software Templates and more making our internal teams' lives easier! | +| [Globo](https://globo.com) | [Carlos GusmΓ£o](https://github.com/caeugusmao), [Guilherme Vierno](https://github.com/vierno), [Denis Aoki](https://github.com/dnsaoki2), [Maycon Dionisio](https://github.com/MayconDionisio), | Reduce the friction of accessing the information engineers need about Globo's digital services through a coherent and centralized experience. | +| [QBE](https://www.qbe.com/) | [Daniel Steel](https://github.com/danielsteelqbe), [Pete Jespers](https://github.com/petejespersqbe) | Developer portal allowing our global teams to explore and create applications, documentation and cloud infrastructure easily and quickly πŸš€ | +| [GoTo](https://www.goto.com) | [Lorenzo Orsatti](https://github.com/lorsatti) | Improve onboarding experience of new developers. Discover faster and painlessly developer documentation, API definitions and team information. Provide useful dev metrics in a central place. Provide easy-to-use templates for new services. | +| [Telstra](https://www.telstra.com.au) | [@kiranpatel11](https://github.com/kiranpatel11), [JasonC](https://github.com/JasonC17) | Primary usage: software catalog and templates
Emerging usage : TechDocs, Explore Ecosystem, TechRadar, etc | +| [Mosaico](https://www.mosaico.com.br/) | [WΓ©dney Yuri](https://github.com/wedneyyuri),[@tino.milton](https://github.com/miltonjacomini) | A centralized service catalog of our documentation for our service engineers. | +| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong πŸ₯°πŸš€ | +| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. πŸš— | +| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. | +| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding | +| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. | +| [EF Education First](https://www.ef.com) | [Daan Boerlage](https://github.com/runebaas), [RafaΕ‚ Nowosielski](https://github.com/rnowosielski) | Our developer portal - primarily used for cataloging and scaffolding with the ambition to expand with more feature adoptions over time | +| [Power Home Remodeling](https://www.techatpower.com) | [Ben Langfeld](https://github.com/benlangfeld) | Developer portal to our internal services, build on open-source software (including Kubernetes) in our own datacenters. Our Portal allows our team members to navigate inherant complexity and standardise. | +| [Livspace](https://www.livspace.com) | [Praveen Kumar](https://github.com/praveen-livspace) | Developer portal, service catalog, tech docs, API docs and plugins | +| [Just Eat Takeaway](https://www.justeattakeaway.com) | [Kim Wilson](https://github.com/kwilson541) | Our developer portal which centralises applications, reduces cognitive load and provides teams insights. | +| [Hopin](https://hopin.com) | [Vladimir Glafirov](https://github.com/vglafirov), [Chloe Lee](https://github.com/msfuko) | Developer portal to streamline the development practices. Integrated with service catalog, software templates, application monitoring, tech docs and plugins. | +| [HBO Max](https://hbomax.com) | [@mdb](https://github.com/mdb), [@nesta219](https://github.com/nesta219), [@nmische](https://github.com/nmische), [@hbomark](https://github.com/hbomark) | Developer portal hosting service catalog and API documentation, as well as cloud infrastructure details, operational visibility tools, and a custom plugin for browsing notable platform change events, such as deployments and configuration updates. | +| [RCHLO](https://www.riachuelo.com.br) & [MIDWAY](https://www.midway.com.br) | [@marcosborges](https://github.com/marcosborges), [@defaultbr](https://github.com/defaultbr) | Self-Service Platform | +| [HP Inc](https://www.hp.com) | [Damon Kaswell](https://github.com/dekoding) | DevEx engagement hub (dev portal: docs, standards, Q&A) and extensive assets catalog (APIs, services, code, data, etc.) for the pan-HP internal developer community. | +| [VMware](https://www.vmware.com) | [@mpriamo](https://github.com/mpriamo), [@krisapplegate](https://github.com/krisapplegate) | Part of [Tanzu Application Platform](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) offering; internal developer portal | +| [UalΓ‘](https://www.uala.com.ar/) | [Santiago Bernal](https://github.com/sabernal) | Initial work being done to centralize documentation for all our microservices and APIs, as well as scaffolding new services and tracking code quality | +| [IKEA IT AB](https://www.ingka.com) | [@bjornramberg](https://github.com/bjornramberg), [@supriyachitale](https://github.com/supriyachitale) | Supporting engineers at scale with self serve access and connecting the dots of our engineering platform and services, enabling product teams to move faster and go further, and unleashing innovation, reuse and co-creation across the organisation. | +| [Invitae](https://www.invitae.com/en) | [@ryan-hanchett](https://github.com/ryan-hanchett), [@gmandler42](https://github.com/gmandler42) | Centralized Developer Experience portal, putting all of our tooling behind a single pane of glass and creating a living service catalog. | +| [Fortum](https://www.fortum.com/) | [@brunoamaroalmeida](https://github.com/brunoamaroalmeida), [@dhaval-vithalani](https://github.com/dhaval-vithalani), [@sunilkumarmohanty](https://github.com/sunilkumarmohanty) | A central portal containing information about our applications, services, processes and other software assets to be used by Fortum software engineering community. | +| [Procore](https://www.procore.com/jobs/engineering) | [@shayon](https://github.com/Shayon), [@jamesdabbs-procore](https://github.com/jamesdabbs-procore) | Developer portal - centralized software catalog and templates to enable self serve and reduce cognitive load. | +| [Bradesco](https://banco.bradesco/html/classic/sobre/index.shtm) | [@danilosoarescardoso](https://github.com/danilosoarescardoso) | Centralized developer portal with software catalog, software templates, techdocs and some plugins from community and by our own. | \ No newline at end of file diff --git a/app-config.yaml b/app-config.yaml index b025064c74..e49e29c45a 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -464,3 +464,6 @@ apacheAirflow: gocd: baseUrl: https://your.gocd.instance.com + +airbrake: + apiKey: ${AIRBRAKE_API_KEY} diff --git a/contrib/chart/backstage/templates/ingress.yaml b/contrib/chart/backstage/templates/ingress.yaml index 3fa052485e..cac9b61553 100644 --- a/contrib/chart/backstage/templates/ingress.yaml +++ b/contrib/chart/backstage/templates/ingress.yaml @@ -15,7 +15,6 @@ metadata: {{- if .Values.issuer.email }} cert-manager.io/cluster-issuer: {{ .Values.issuer.clusterIssuer }} {{- end }} - kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/ssl-redirect: "false" nginx.ingress.kubernetes.io/configuration-snippet: | if ($scheme = https) { diff --git a/contrib/docker/devops/Dockerfile b/contrib/docker/devops/Dockerfile index 9bb80a0a2c..a7c194618a 100644 --- a/contrib/docker/devops/Dockerfile +++ b/contrib/docker/devops/Dockerfile @@ -9,7 +9,8 @@ WORKDIR /tmp # update package sources # `--virtual` is used to enable removal of these dependencies as a named group -# - python: required by node-gyp +# - python3: required by node-gyp +# - g++: required to build @vscode/sqlite3 # - pixman: required by node-canvas # - pkgconfig: required by pixman # -------------------------------------------- @@ -32,7 +33,8 @@ WORKDIR /tmp RUN apk update \ && apk add --no-cache \ --virtual ${APK_VIRTUAL_NAME} \ - python \ + python3 \ + g++ \ pixman \ pkgconfig \ alpine-sdk \ @@ -51,6 +53,10 @@ RUN wget -qO- ${VALE_INSTALL_URL} \ | tar xvz -C /bin vale \ && chmod +x /bin/vale +# needed for sqlite3 build that needs python +RUN ln -s /usr/bin/python3 /usr/bin/python && \ + ln -s /usr/bin/pip3 /usr/bin/pip + RUN mkdir /app WORKDIR /app diff --git a/docs/assets/getting-started/sidebar-with-catalog.png b/docs/assets/getting-started/sidebar-with-catalog.png new file mode 100644 index 0000000000..d80346c211 Binary files /dev/null and b/docs/assets/getting-started/sidebar-with-catalog.png differ diff --git a/docs/assets/getting-started/sidebar-without-catalog.png b/docs/assets/getting-started/sidebar-without-catalog.png new file mode 100644 index 0000000000..bfeab13235 Binary files /dev/null and b/docs/assets/getting-started/sidebar-without-catalog.png differ diff --git a/docs/assets/getting-started/simple-homepage.png b/docs/assets/getting-started/simple-homepage.png new file mode 100644 index 0000000000..128707e9ff Binary files /dev/null and b/docs/assets/getting-started/simple-homepage.png differ diff --git a/docs/auth/index.md b/docs/auth/index.md index e407480f65..6bda35232a 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -56,18 +56,15 @@ allows a single auth backend to serve multiple environments, such as running a local frontend against a deployed backend. The provider configuration matching the local `auth.environment` setting will be selected. -### Adding the provider to the sign-in page +## Using an authentication provider for sign-in -After configuring an authentication provider, the `app` frontend package needs a -small update to show this provider as a login option. The `SignInPage` component -handles this, and takes either a `provider` or `providers` (array) prop of -`SignInProviderConfig` definitions. +If you want to use an authentication provider for sign-in, as opposed to just accessing external resources, you'll need to configure that in your app as well. This is done by providing a custom `SignInPage` component to the app, which will require the user to sign in before they can access the app. Note that this does not block access to the app, which you can read more about [here](./using-auth.md). -These reference the `ApiRef` exported by the provider. Again, an example using -GitHub that can be adapted to any of the built-in providers: +If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`, which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions. These reference the `ApiRef` exported for the provider. + +Again, the following example for GitHub shows the additions needed to `packages/app/src/App.tsx`, and can be adapted to any of the built-in providers: ```diff -# packages/app/src/App.tsx + import { githubAuthApiRef } from '@backstage/core-plugin-api'; + import { SignInProviderConfig, SignInPage } from '@backstage/core-components'; @@ -78,8 +75,8 @@ GitHub that can be adapted to any of the built-in providers: + apiRef: githubAuthApiRef, +}; + -const app = createApp({ - apis, + const app = createApp({ + apis, + components: { + SignInPage: props => ( + + ), + }, - bindRoutes({ bind }) { + bindRoutes({ bind }) { ``` To also allow unauthenticated guest access, use the `providers` prop for `SignInPage`: ```diff -const app = createApp({ - apis, + const app = createApp({ + apis, + components: { + SignInPage: props => ( + + ), + }, - bindRoutes({ bind }) { + bindRoutes({ bind }) { ``` ## Adding a custom authentication provider @@ -119,3 +116,26 @@ Backstage uses [Passport](http://www.passportjs.org/) under the hood, which has a wide library of authentication strategies for different providers. See [Add authentication provider](add-auth-provider.md) for details on adding a new Passport-supported authentication method. + +## Custom ScmAuthApi Implementation + +If you are using any custom authentication providers, like for example one for GitHub Enterprise, then you are likely to need a custom implementation of the [`ScmAuthApi`](https://backstage.io/docs/reference/integration-react.scmauthapi). It is an API used to authenticate towards different SCM systems in a generic way, based on what resource is being accessed, and is used for example by the Scaffolder (Software Templates) and Catalog Import plugins. + +To set up a custom `ScmAuthApi` implementation, you'll need to add an API factory entry to `packages/app/src/apis.ts`. The following example shows an implementation that supports both public GitHub via `githubAuthApi` as well as a GitHub Enterprise installation hosted at `ghe.example.com` via `gheAuthApi`: + +```ts +createApiFactory({ + api: scmAuthApiRef, + deps: { + gheAuthApi: gheAuthApiRef, + githubAuthApi: githubAuthApiRef, + }, + factory: ({ githubAuthApi, gheAuthApi }) => + ScmAuth.merge( + ScmAuth.forGithub(githubAuthApi), + ScmAuth.forGithub(gheAuthApi, { + host: 'ghe.example.com', + }), + ), +}); +``` diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 6f58abe769..36967f352a 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -56,7 +56,7 @@ Once the host build is complete, we are ready to build our image. The following `Dockerfile` is included when creating a new app with `@backstage/create-app`: ```Dockerfile -FROM node:14-buster-slim +FROM node:16-bullseye-slim WORKDIR /app # Copy repo skeleton first, to avoid unnecessary docker cache invalidation. @@ -65,6 +65,12 @@ WORKDIR /app COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz +# install sqlite3 dependencies +RUN apt-get update && \ + apt-get install -y libsqlite3-dev python3 cmake g++ && \ + rm -rf /var/lib/apt/lists/* && \ + yarn config set python /usr/bin/python3 + RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. @@ -134,23 +140,28 @@ the repo root: ```Dockerfile # Stage 1 - Create yarn install skeleton layer -FROM node:14-buster-slim AS packages +FROM node:16-bullseye-slim AS packages WORKDIR /app COPY package.json yarn.lock ./ COPY packages packages + # Comment this out if you don't have any internal plugins COPY plugins plugins RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -exec rm -rf {} \+ # Stage 2 - Install dependencies and build packages -FROM node:14-buster-slim AS build +FROM node:16-bullseye-slim AS build WORKDIR /app COPY --from=packages /app . +# install sqlite3 dependencies +RUN apt-get update && apt-get install -y libsqlite3-dev python3 cmake g++ && \ + yarn config set python /usr/bin/python3 + RUN yarn install --frozen-lockfile --network-timeout 600000 && rm -rf "$(yarn cache dir)" COPY . . @@ -159,7 +170,7 @@ RUN yarn tsc RUN yarn --cwd packages/backend backstage-cli backend:bundle --build-dependencies # Stage 3 - Build the actual backend image and install production dependencies -FROM node:14-buster-slim +FROM node:16-bullseye-slim WORKDIR /app @@ -167,6 +178,12 @@ WORKDIR /app COPY --from=build /app/yarn.lock /app/package.json /app/packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz +# install sqlite3 dependencies +RUN apt-get update && \ + apt-get install -y libsqlite3-dev python3 cmake g++ && \ + rm -rf /var/lib/apt/lists/* && \ + yarn config set python /usr/bin/python3 + RUN yarn install --frozen-lockfile --production --network-timeout 600000 && rm -rf "$(yarn cache dir)" # Copy the built packages from the build stage diff --git a/docs/features/search/getting-started.md b/docs/features/search/getting-started.md index 285e399cb4..7c3717e22e 100644 --- a/docs/features/search/getting-started.md +++ b/docs/features/search/getting-started.md @@ -114,15 +114,13 @@ const routes = ( In `Root.tsx`, add the `SidebarSearchModal` component: ```bash -import { SidebarSearchModal, SearchContextProvider } from '@backstage/plugin-search'; +import { SidebarSearchModal } from '@backstage/plugin-search'; export const Root = ({ children }: PropsWithChildren<{}>) => ( - - - + ... ``` diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index b14fd732d7..f8a44ceef6 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -472,8 +472,8 @@ type CacheItem = { export class SystemXReaderProcessor implements CatalogProcessor { constructor(private readonly reader: UrlReader) {} - // It's recommended to give the processor a unique name. getProcessorName() { + // The processor name must be unique. return 'system-x-processor'; } diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index 8122fefdcd..a5dc8c3c54 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -123,7 +123,7 @@ Options: --no-pull Do not pull the latest docker image --no-docker Do not use Docker, use MkDocs executable and plugins in current user environment. --techdocs-ref The repository hosting documentation source files e.g. - github:https://ghe.mycompany.net.com/org/repo. + url:https://ghe.mycompany.net.com/org/repo. This value is same as the backstage.io/techdocs-ref annotation of the corresponding Backstage entity. It is completely fine to skip this as it is only being used to set repo_url in mkdocs.yml diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index fc68008ae8..34eca2429a 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -257,68 +257,4 @@ const LogoFull = () => { ## Custom Homepage In addition to a custom theme, a custom logo, you can also customize the -homepage of your app. To do that we need to go through a few steps. - -### Setting up the Home Page - -1. Create a Home Page Component that will be used for composition. - -`packages/app/src/components/home/HomePage.tsx` - -```tsx -import React from 'react'; - -export const HomePage = () => { - return { - /* TODO: Compose a Home Page here */ - }; -}; -``` - -2. Add a route where the homepage will live, presumably `/`. - -`packages/app/src/App.tsx` - -```tsx -import { HomepageCompositionRoot } from '@backstage/plugin-home'; -import { HomePage } from './components/home/HomePage'; - -// ... -}> - -; -// ... -``` - -### Composing your Home Page - -Composing a Home Page is no different from creating a regular React Component, -i.e. the App Integrator is free to include whatever content they like. However, -there are components developed with the Home Page in mind. If you are looking -for components to use when composing your homepage, you can take a look at the -[collection of Homepage components](https://backstage.io/?path=/story/plugins-home-components) -in storybook. If you don't find a component that suits your needs but want to -contribute, check the -[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing). - -> If you want to use one of the available homepage templates you can find the -> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates) -> in the storybook under the "Home" plugin. And if you would like to contribute -> a template, please see the -> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing) - -```tsx -import React from 'react'; -import Grid from '@material-ui/core/Grid'; -import { HomePageCompanyLogo } from '@backstage/plugin-home'; - -export const HomePage = () => { - return ( - - - - - - ); -}; -``` +homepage of your app. Read the full guide on the [next page](homepage.md). diff --git a/docs/getting-started/create-an-app.md b/docs/getting-started/create-an-app.md index 1d65f25d1b..05c12ffb75 100644 --- a/docs/getting-started/create-an-app.md +++ b/docs/getting-started/create-an-app.md @@ -16,8 +16,7 @@ may want to [Run Backstage Locally](./running-backstage-locally.md) instead. ## Create an app To create a Backstage app, you will need to have -[Node.js](https://nodejs.org/en/download/) Active LTS Release installed -(currently v14). +Node.js [Active LTS Release](https://nodejs.org/en/about/releases/) installed. Backstage provides a utility for creating new apps. It guides you through the initial setup of selecting the name of the app and a database for the backend. diff --git a/docs/getting-started/homepage.md b/docs/getting-started/homepage.md new file mode 100644 index 0000000000..59272a285b --- /dev/null +++ b/docs/getting-started/homepage.md @@ -0,0 +1,166 @@ +--- +id: homepage +title: Backstage homepage - Setup and Customization +description: Documentation on setting up and customizing Backstage homepage +--- + +## Homepage + +Having a good Backstage homepage can significantly improve the discoverability of the platform. You want your users to find all the things they need right from the homepage and never have to remember direct URLs in Backstage. The [Home plugin](https://github.com/backstage/backstage/tree/master/plugins/home) introduces a system for composing a homepage for Backstage in order to surface relevant info and provide convenient shortcuts for common tasks. It's designed with composability in mind with an open ecosystem that allows anyone to contribute with any component, to be included in any homepage. + +For App Integrators, the system is designed to be composable to give total freedom in designing a Homepage that suits the needs of the organization. From the perspective of a Component Developer who wishes to contribute with building blocks to be included in Homepages, there's a convenient interface for bundling the different parts and exporting them with both error boundary and lazy loading handled under the surface. + +At the end of this tutorial, you can expect: + +- Your Backstage app to have a dedicated homepage instead of Software Catalog. +- Understand the composability of homepage and how to start customizing it for your own organization. + +### Prerequisites + +Before we begin, make sure + +- You have created your own standalone Backstage app using [`@backstage/create-app`](index.md#create-your-backstage-app) and not using a fork of the [backstage](https://github.com/backstage/backstage) repository. +- You do not have an existing homepage, and by default you are redirected to Software Catalog when you open Backstage. + +Now, let's get started by installing the home plugin and creating a simple homepage for your Backstage app. + +### Setup homepage + +#### 1. Install the plugin + +``` +# From your Backstage application directory +cd packages/app +yarn add @backstage/plugin-home +``` + +#### 2. Create a new HomePage component + +Inside your `packages/app` directory, create a new file where our new homepage component is going to live. Create `packages/app/src/components/home/HomePage.tsx` with the following initial code + +```tsx +import React from 'react'; + +export const HomePage = () => { + /* We will shortly compose a pretty homepage here. */ + return

Welcome to Backstage!

; +}; +``` + +#### 3. Update router for the root `/` route + +If you don't have a homepage already, most likely you have a redirect setup to use the Catalog homepage as a homepage. + +Inside your `packages/app/src/App.tsx`, look for + +```tsx +const routes = ( + + +``` + +Let's replace the `` line and use the new component we created in the previous step as the new homepage. + +```diff +// File: packages/app/src/App.tsx + ++ import { HomepageCompositionRoot } from '@backstage/plugin-home'; ++ import { HomePage } from './components/home/HomePage'; + +// ... +const routes = ( + +- ++ }> ++ ++ +// ... + +) +``` + +### 4. Update sidebar items + +Let's update the route for "Home" in the Backstage sidebar to point to the new homepage. We'll also add a Sidebar item to quickly open Catalog. + + + + + + + + +
Sidebar without Catalog + Sidebar with Catalog +
BeforeAfter
+ +The code for the Backstage sidebar is most likely inside your [`packages/app/src/components/Root/Root.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/Root/Root.tsx). + +Let's make the following changes + +```diff +// Other imports ++ import CategoryIcon from '@material-ui/icons/Category'; + +export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + + # ... + }> + {/* Global nav, not org-specific */} +- ++ ++ + + + + + {/* End global nav */} + +``` + +That's it! You should now have _(although slightly boring)_ a homepage! + +Screenshot of a blank homepage + +In the next steps, we will make it interesting and useful! + +### Use the default template + +There is a default homepage template ([storybook link](https://backstage.io/storybook/?path=/story/plugins-home-templates--default-template)) which we will use to set up our homepage. Checkout the [blog post announcement](https://backstage.io/blog/2022/01/25/backstage-homepage-templates) about the Backstage homepage templates for more information. + + + +### Composing your homepage + +Composing a homepage is no different from creating a regular React Component, +i.e. the App Integrator is free to include whatever content they like. However, +there are components developed with the homepage in mind. If you are looking +for components to use when composing your homepage, you can take a look at the +[collection of Homepage components](https://backstage.io/storybook?path=/story/plugins-home-components) +in storybook. If you don't find a component that suits your needs but want to +contribute, check the +[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing). + +> If you want to use one of the available homepage templates you can find the +> [templates](https://backstage.io/storybook/?path=/story/plugins-home-templates) +> in the storybook under the "Home" plugin. And if you would like to contribute +> a template, please see the +> [Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing) + +```tsx +import React from 'react'; +import Grid from '@material-ui/core/Grid'; +import { HomePageCompanyLogo } from '@backstage/plugin-home'; + +export const HomePage = () => { + return ( + + + + + + ); +}; +``` diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index a622313739..8c2f6bc865 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -25,7 +25,7 @@ guide to do a repository-based installation. [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) - An account with elevated rights to install the dependencies - `curl` or `wget` installed -- Node.js Active LTS Release installed (currently v14) using one of these +- Node.js [Active LTS Release](https://nodejs.org/en/about/releases/) installed using one of these methods: - Using `nvm` (recommended) - [Installing nvm](https://github.com/nvm-sh/nvm#install--update-script) diff --git a/docs/getting-started/running-backstage-locally.md b/docs/getting-started/running-backstage-locally.md index daad7bf195..3443b85285 100644 --- a/docs/getting-started/running-backstage-locally.md +++ b/docs/getting-started/running-backstage-locally.md @@ -13,13 +13,14 @@ trying to contribute, follow the instructions to - Node.js -First make sure you are using Node.js with an Active LTS Release, currently v14. +First make sure you are using Node.js with an [Active LTS Release](https://nodejs.org/en/about/releases/). This is made easy with a version manager such as [nvm](https://github.com/nvm-sh/nvm) which allows for version switching. ```bash -# Installing a new version -nvm install 14 +# Installing current LTS release +nvm install --lts +> Installing latest LTS version. > Downloading and installing node v14.15.1... > Now using node v14.15.1 (npm v6.14.8) diff --git a/docs/integrations/github/locations.md b/docs/integrations/github/locations.md index 330b03eab9..3395c61117 100644 --- a/docs/integrations/github/locations.md +++ b/docs/integrations/github/locations.md @@ -57,6 +57,22 @@ public GitHub, for which we can infer them). The `apiBaseUrl` will always be preferred over the other if a `token` is given, otherwise `rawBaseUrl` will be preferred. +### Token scopes + +When creating a personal access token on GitHub, you must select scopes to +define the level of access for the token. The scopes required vary depending on +your use of the integration: + +- Reading software components: + - `repo` +- Reading organization data: + - `read:org` + - `read:user` + - `user:email` +- Publishing software templates: + - `repo` + - `workflow` (if templates include GitHub workflows) + ## Authentication with GitHub Apps Alternatively, Backstage can use GitHub Apps for backend authentication. This diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index 7140ffa505..5843944e8a 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -22,19 +22,6 @@ entities that mirror your org setup. The processor that performs the import, `GithubOrgReaderProcessor`, comes installed with the default setup of Backstage. -If you have _replaced_ the set of processors in your installation using -`replaceProcessors`, you can import and add it as follows: - -```ts -// Typically in packages/backend/src/plugins/catalog.ts -import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend'; - -builder.replaceProcessors( - GithubOrgReaderProcessor.fromConfig(config, { logger }), - // ... -); -``` - ## Configuration The following configuration enables an import of the teams and users under the @@ -51,10 +38,12 @@ If Backstage is configured to use GitHub Apps authentication you must grant `Read-Only` access for `Members` under `Organization` in order to ingest users correctly. You can modify the app's permissions under the organization settings, `https://github.com/organizations/{ORG}/settings/apps/{APP_NAME}/permissions`. + ![permissions](../../assets/integrations/github/permissions.png) **Please note that when you change permissions, the app owner will get an email that must be approved first before the changes are applied.** + ![email](../../assets/integrations/github/email.png) Locations point out the specific org(s) you want to import. The `type` of these @@ -65,3 +54,22 @@ The authorization for loading org information comes from a configured [GitHub integration](locations.md#configuration). When using a personal access token, the token needs to have at least the scopes `read:org`, `read:user`, and `user:email` in the given `target`. + +## Addendum + +Some Backstage apps have _replaced_ the catalog processors to override the +default catalog processing behavior. These apps will already have a call to +`replaceProcessors` in the catalog initialization. + +In the unlikely scenario that this applies to your app, you can import and +add the `GithubOrgReaderProcessor` as follows: + +```ts +// Typically in packages/backend/src/plugins/catalog.ts +import { GithubOrgReaderProcessor } from '@backstage/plugin-catalog-backend'; + +builder.replaceProcessors( + // ... other processor replacements + GithubOrgReaderProcessor.fromConfig(config, { logger }), +); +``` diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index fdfede6e05..75f0606752 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -334,13 +334,19 @@ The following is an example of a `Dockerfile` that can be used to package the output of `backstage-cli backend:bundle` into an image: ```Dockerfile -FROM node:14-buster-slim +FROM node:16-bullseye-slim WORKDIR /app COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz -RUN yarn install --production --frozen-lockfile --network-timeout 300000 && rm -rf "$(yarn cache dir)" +# install sqlite3 dependencies +RUN apt-get update && \ + apt-get install -y libsqlite3-dev python3 cmake g++ && \ + rm -rf /var/lib/apt/lists/* && \ + yarn config set python /usr/bin/python3 + +RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" COPY packages/backend/dist/bundle.tar.gz app-config.yaml ./ RUN tar xzf bundle.tar.gz && rm bundle.tar.gz @@ -444,8 +450,9 @@ working directory to the package that the test is in. Where small customizations are needed, such as setting coverage thresholds or support for specific transforms, it is possible to override the Jest -configuration through the `"jest"` field in `package.json`. These overrides will -be loaded in from all `package.json` files in the directory ancestry, meaning +configuration through the `"jest"` field in `package.json`. For a full list of +options, see the [Jest documentation](https://jestjs.io/docs/en/configuration). +These overrides will be loaded in from all `package.json` files in the directory ancestry, meaning that you can place common configuration in the `package.json` at the root of a monorepo. If multiple overrides are found, they will be merged together with configuration further down in the directory tree taking precedence. @@ -464,6 +471,45 @@ The overrides in a single `package.json` may for example look like this: }, ``` +If you want to configure editor integration for tests we recommend executing the bundled configuration directly with Jest rather than running through the Yarn test script. For example, with the Jest extension for VS Code the configuration would look something like this: + +```jsonc +{ + "jest.jestCommandLine": "node_modules/.bin/jest --config node_modules/@backstage/cli/config/jest.js", + // In a large repo like the Backstage main repo you likely want to disable + // watch mode and the initial test run too, leaving just manual and perhaps + // on-save test runs in place. + "jest.autoRun": { + "watch": false, + "onSave": "test-src-file" + } +} +``` + +If you also want to enable source maps when debugging tests, you can do so by setting the `ENABLE_SOURCE_MAPS` environment variable. For example, a complete launch configuration for VS Code debugging may look like this: + +```json +{ + "type": "node", + "name": "vscode-jest-tests", + "request": "launch", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "program": "${workspaceFolder}/node_modules/.bin/jest", + "cwd": "${workspaceFolder}", + "env": { + "ENABLE_SOURCE_MAPS": "true" + }, + "args": [ + "--config", + "node_modules/@backstage/cli/config/jest.js", + "--runInBand", + "--watchAll=false" + ] +} +``` + ## Publishing Package publishing is an optional part of the Backstage build system and not diff --git a/docs/local-dev/cli-commands.md b/docs/local-dev/cli-commands.md index daf53ac0b2..eff6404e3b 100644 --- a/docs/local-dev/cli-commands.md +++ b/docs/local-dev/cli-commands.md @@ -440,22 +440,7 @@ a yarn workspaces monorepo by automatically creating one grouped configuration that includes all packages that have `backstage-cli test` in their package `test` script. -If needed, the configuration can be extended using a `"jest"` field in -`package.json`, both within the target package and the monorepo root, with -configuration in the target package taking precedence. Refer to the -[Jest configuration documentation](https://jestjs.io/docs/en/configuration) for -a full list of configuration options. - -In addition to the Jest configuration there's an optional `transformModules` -option, which is an array of module names to include in transformations. -Normally modules inside `node_modules` are not transformed, but there are cases -were published packages are not transpiled far enough to be usable by Jest, in -which case you need to enable transform of them. - -Another way to override the Jest configuration is to place a `jest.config.js` or -`jest.config.ts` file in the package root. As opposed to the `package.json` way -of overriding config, this completely removes the base config, and so you need -to set it up from scratch. +For more information about configuration overrides and editor support, see the [Jest Configuration section](./cli-build-system.md#jest-configuration) in the build system documentation. ```text Usage: backstage-cli test [options] diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index 1be1502b6b..434c9a4882 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -109,11 +109,21 @@ privateKey: | This will result in backstage preventing the use of any installation that is not within the allow list. -### Permissions for pull requests +### App permissions -These are the minimum permissions required for creating a pull request with -Backstage software templates: +When creating a GitHub App, you must select permissions to define the level of +access for the app. The permissions required vary depending on your use of the +integration: -- Read and Write permissions for `Contents`. -- Read and write permissions for `Pull Requests` and `Issues`. -- Read permissions on `Metadata`. +- Reading software components: + - `Contents`: `Read-only` +- Reading organization data: + - `Members`: `Read-only` +- Publishing software templates: + + - `Administration`: `Read & write` (for creating repositories) + - `Contents`: `Read & write` + - `Metadata`: `Read-only` + - `Pull requests`: `Read & write` + - `Issues`: `Read & write` + - `Workflows`: `Read & write` (if templates include GitHub workflows) diff --git a/docs/plugins/integrating-plugin-into-software-catalog.md b/docs/plugins/integrating-plugin-into-software-catalog.md index 71430e25a0..97efa56ac3 100644 --- a/docs/plugins/integrating-plugin-into-software-catalog.md +++ b/docs/plugins/integrating-plugin-into-software-catalog.md @@ -107,7 +107,7 @@ const systemPage = ( - + {/* Adding a new tab to the system view */} diff --git a/docs/publishing.md b/docs/publishing.md index 2951f7d30b..fbbef93493 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -65,8 +65,8 @@ process is used to release an emergency fix as version `6.5.1` in the patch rele master branch as well. Create a PR that contains the following: - [ ] The fix, which you can likely cherry-pick from your patch branch: `git cherry-pick origin/patch/v1.18.0^` - - [ ] An updated `CHANGELOG.md` of all patched patches from the tip of the patch branch, which you can get using `git checkout origin/patch/v1.18.0 -- plugins/foo/CHANGELOG.md`. - - [ ] A changeset with the message "Applied the fix from version `6.5.1` of this package, which is part of the `v1.18.1` release of Backstage.", + - [ ] An updated `CHANGELOG.md` of all patched packages from the tip of the patch branch, `git checkout origin/patch/v1.18.0 -- {packages,plugins}/*/CHANGELOG.md`. + - [ ] A changeset with the message "Applied the fix from version `6.5.1` of this package, which is part of the `v1.18.1` release of Backstage." - [ ] An entry in `.changeset/patched.json` that sets the current release version to `6.5.1`: ```json diff --git a/microsite/blog/2022-01-25-backstage-homepage-templates.md b/microsite/blog/2022-01-25-backstage-homepage-templates.md index 7ed5ee92e3..8ca8b7373e 100644 --- a/microsite/blog/2022-01-25-backstage-homepage-templates.md +++ b/microsite/blog/2022-01-25-backstage-homepage-templates.md @@ -33,7 +33,7 @@ _Example of the default homepage template in Backstage Storybook_ ## How to get started -To get started, you first need to set up your homepage plugin in the app if you have not already, then you can move on to composing your homepage. You can find our step-by-step documentation of how to do this under the [App Configuration - Customize the look-and-feel of your App documentation](https://backstage.io/docs/getting-started/app-custom-theme#custom-homepage). You can also access the [Backstage UI Kit in Figma](https://www.figma.com/file/nUaAw56hTgC0RIOYkuLSrB/Backstage-Design-System?node-id=2185%3A2978) to duplicate your own version and play around with a fitting homepage for your own organization. +To get started, you first need to set up your homepage plugin in the app if you have not already, then you can move on to composing your homepage. You can find our step-by-step documentation of how to do this under the [App Configuration - Customize the look-and-feel of your App documentation](https://backstage.io/docs/getting-started/homepage). You can also access the [Backstage UI Kit in Figma](https://www.figma.com/file/nUaAw56hTgC0RIOYkuLSrB/Backstage-Design-System?node-id=2185%3A2978) to duplicate your own version and play around with a fitting homepage for your own organization. ![Example of homepage components in the Backstage UI Kit in Figma](assets/22-01-25/homepage-components-figma.png) _Example of the homepage components in the Backstage UI Kit in Figma_ diff --git a/microsite/data/plugins/airbrake.yaml b/microsite/data/plugins/airbrake.yaml index 96de75c002..29c1f394d7 100644 --- a/microsite/data/plugins/airbrake.yaml +++ b/microsite/data/plugins/airbrake.yaml @@ -4,6 +4,6 @@ author: Simply Business authorUrl: https://github.com/simplybusiness/ category: Monitoring description: Access Airbrake error monitoring and other integrations from within Backstage -documentation: https://github.com/backstage/backstage/blob/master/plugins/airbrake/README.md +documentation: https://github.com/backstage/backstage/blob/master/plugins/airbrake iconUrl: https://wp-assets.airbrake.io/wp-content/uploads/2020/10/05222904/Square-white-A-on-Orange.png npmPackageName: '@backstage/plugin-airbrake' diff --git a/microsite/pages/en/link.js b/microsite/pages/en/link.js index ddac35e545..727b15bfd8 100644 --- a/microsite/pages/en/link.js +++ b/microsite/pages/en/link.js @@ -5,6 +5,7 @@ const React = require('react'); const redirects = { 'bind-routes': '/docs/plugins/composability#binding-external-routes-in-the-app', + 'scm-auth': '/docs/auth/#custom-scmauthapi-implementation', }; const fallback = '/docs'; diff --git a/microsite/sidebars.json b/microsite/sidebars.json index cb7c0d5036..5369182013 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -22,7 +22,8 @@ "label": "App configuration", "ids": [ "getting-started/configure-app-with-plugins", - "getting-started/app-custom-theme" + "getting-started/app-custom-theme", + "getting-started/homepage" ] }, "getting-started/keeping-backstage-updated", diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 01226a9bf9..81d28c7ab7 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -6499,9 +6499,9 @@ url-parse-lax@^3.0.0: prepend-http "^2.0.0" url-parse@^1.4.3: - version "1.5.3" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" - integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== + version "1.5.7" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.7.tgz#00780f60dbdae90181f51ed85fb24109422c932a" + integrity sha512-HxWkieX+STA38EDk7CE9MEryFeHCKzgagxlGvsdS7WBImq9Mk+PGwiT56w82WI3aicwJA8REp42Cxo98c8FZMA== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" diff --git a/package.json b/package.json index 242c64c8bb..9745b6d867 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "**/@roadiehq/**/@backstage/plugin-catalog": "*", "**/@roadiehq/**/@backstage/catalog-model": "*" }, - "version": "0.67.0", + "version": "0.68.0", "dependencies": { "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.15.0", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 74313008cd..9b9f57f4a5 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/app-defaults +## 0.1.8 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-app-api@0.5.3 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-permission-react@0.3.1 + - @backstage/theme@0.2.15 + ## 0.1.7 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index c7cb87faa4..364baa6e83 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "0.1.7", + "version": "0.1.8", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,19 +24,20 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-app-api": "^0.5.2", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-app-api": "^0.5.3", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "react-router-dom": "6.0.0-beta.0" @@ -42,8 +46,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@types/jest": "^26.0.7", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 1139bf2cbb..03f570005f 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,59 @@ # example-app +## 0.2.65 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.14.0 + - @backstage/core-app-api@0.5.3 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-airbrake@0.2.0 + - @backstage/plugin-apache-airflow@0.1.7 + - @backstage/plugin-api-docs@0.7.3 + - @backstage/plugin-azure-devops@0.1.15 + - @backstage/plugin-badges@0.2.23 + - @backstage/plugin-catalog@0.8.0 + - @backstage/plugin-catalog-import@0.8.2 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/plugin-circleci@0.2.38 + - @backstage/plugin-cloudbuild@0.2.36 + - @backstage/plugin-code-coverage@0.1.26 + - @backstage/plugin-cost-insights@0.11.21 + - @backstage/plugin-explore@0.3.30 + - @backstage/plugin-gcp-projects@0.3.18 + - @backstage/plugin-github-actions@0.4.36 + - @backstage/plugin-gocd@0.1.5 + - @backstage/plugin-graphiql@0.2.31 + - @backstage/plugin-home@0.4.15 + - @backstage/plugin-jenkins@0.5.21 + - @backstage/plugin-kafka@0.2.29 + - @backstage/plugin-kubernetes@0.5.8 + - @backstage/plugin-lighthouse@0.2.38 + - @backstage/plugin-newrelic@0.3.17 + - @backstage/plugin-newrelic-dashboard@0.1.7 + - @backstage/plugin-org@0.4.3 + - @backstage/plugin-pagerduty@0.3.26 + - @backstage/plugin-permission-react@0.3.1 + - @backstage/plugin-rollbar@0.3.27 + - @backstage/plugin-scaffolder@0.12.3 + - @backstage/plugin-search@0.7.0 + - @backstage/plugin-sentry@0.3.37 + - @backstage/plugin-shortcuts@0.2.0 + - @backstage/plugin-tech-insights@0.1.9 + - @backstage/plugin-tech-radar@0.5.6 + - @backstage/plugin-techdocs@0.13.4 + - @backstage/plugin-todo@0.2.1 + - @backstage/plugin-user-settings@0.3.20 + - @backstage/app-defaults@0.1.8 + - @backstage/catalog-model@0.10.0 + - @backstage/search-common@0.2.3 + - @backstage/theme@0.2.15 + - @backstage/plugin-catalog-common@0.1.3 + - @backstage/plugin-catalog-graph@0.2.11 + ## 0.2.64 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index bdade7974a..d1f63b1fd2 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,65 +1,68 @@ { "name": "example-app", - "version": "0.2.64", + "version": "0.2.65", "private": true, + "backstage": { + "role": "frontend" + }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-airbrake": "^0.1.3", - "@backstage/plugin-api-docs": "^0.7.2", - "@backstage/plugin-azure-devops": "^0.1.14", - "@backstage/plugin-apache-airflow": "^0.1.6", - "@backstage/plugin-badges": "^0.2.22", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/plugin-catalog-graph": "^0.2.10", - "@backstage/plugin-catalog-import": "^0.8.1", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-circleci": "^0.2.37", - "@backstage/plugin-cloudbuild": "^0.2.35", - "@backstage/plugin-code-coverage": "^0.1.25", - "@backstage/plugin-cost-insights": "^0.11.20", - "@backstage/plugin-explore": "^0.3.29", - "@backstage/plugin-gcp-projects": "^0.3.17", - "@backstage/plugin-github-actions": "^0.4.35", - "@backstage/plugin-gocd": "^0.1.4", - "@backstage/plugin-graphiql": "^0.2.30", - "@backstage/plugin-home": "^0.4.14", - "@backstage/plugin-jenkins": "^0.5.20", - "@backstage/plugin-kafka": "^0.2.28", - "@backstage/plugin-kubernetes": "^0.5.7", - "@backstage/plugin-lighthouse": "^0.2.37", - "@backstage/plugin-newrelic": "^0.3.16", - "@backstage/plugin-newrelic-dashboard": "^0.1.6", - "@backstage/plugin-org": "^0.4.2-next.0", - "@backstage/plugin-pagerduty": "0.3.25", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/plugin-rollbar": "^0.3.26", - "@backstage/plugin-scaffolder": "^0.12.2", - "@backstage/plugin-search": "^0.6.2", - "@backstage/plugin-sentry": "^0.3.36", - "@backstage/plugin-shortcuts": "^0.1.22", - "@backstage/plugin-tech-radar": "^0.5.5", - "@backstage/plugin-techdocs": "^0.13.3", - "@backstage/plugin-todo": "^0.2.0", - "@backstage/plugin-user-settings": "^0.3.19", - "@backstage/search-common": "^0.2.2", - "@backstage/plugin-tech-insights": "^0.1.8", - "@backstage/theme": "^0.2.14", + "@backstage/app-defaults": "^0.1.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-airbrake": "^0.2.0", + "@backstage/plugin-api-docs": "^0.7.3", + "@backstage/plugin-azure-devops": "^0.1.15", + "@backstage/plugin-apache-airflow": "^0.1.7", + "@backstage/plugin-badges": "^0.2.23", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/plugin-catalog-graph": "^0.2.11", + "@backstage/plugin-catalog-import": "^0.8.2", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-circleci": "^0.2.38", + "@backstage/plugin-cloudbuild": "^0.2.36", + "@backstage/plugin-code-coverage": "^0.1.26", + "@backstage/plugin-cost-insights": "^0.11.21", + "@backstage/plugin-explore": "^0.3.30", + "@backstage/plugin-gcp-projects": "^0.3.18", + "@backstage/plugin-github-actions": "^0.4.36", + "@backstage/plugin-gocd": "^0.1.5", + "@backstage/plugin-graphiql": "^0.2.31", + "@backstage/plugin-home": "^0.4.15", + "@backstage/plugin-jenkins": "^0.5.21", + "@backstage/plugin-kafka": "^0.2.29", + "@backstage/plugin-kubernetes": "^0.5.8", + "@backstage/plugin-lighthouse": "^0.2.38", + "@backstage/plugin-newrelic": "^0.3.17", + "@backstage/plugin-newrelic-dashboard": "^0.1.7", + "@backstage/plugin-org": "^0.4.3", + "@backstage/plugin-pagerduty": "0.3.26", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/plugin-rollbar": "^0.3.27", + "@backstage/plugin-scaffolder": "^0.12.3", + "@backstage/plugin-search": "^0.7.0", + "@backstage/plugin-sentry": "^0.3.37", + "@backstage/plugin-shortcuts": "^0.2.0", + "@backstage/plugin-tech-radar": "^0.5.6", + "@backstage/plugin-techdocs": "^0.13.4", + "@backstage/plugin-todo": "^0.2.1", + "@backstage/plugin-user-settings": "^0.3.20", + "@backstage/search-common": "^0.2.3", + "@backstage/plugin-tech-insights": "^0.1.9", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@octokit/rest": "^18.5.3", - "@roadiehq/backstage-plugin-github-insights": "^1.4.2", - "@roadiehq/backstage-plugin-github-pull-requests": "^1.3.2", - "@roadiehq/backstage-plugin-travis-ci": "^1.3.2", - "@roadiehq/backstage-plugin-buildkite": "^1.3.4", + "@roadiehq/backstage-plugin-github-insights": "^1.5.0", + "@roadiehq/backstage-plugin-github-pull-requests": "^1.4.0", + "@roadiehq/backstage-plugin-travis-ci": "^1.3.6", + "@roadiehq/backstage-plugin-buildkite": "^1.3.8", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^17.0.2", @@ -71,8 +74,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/test-utils": "^0.2.4", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/test-utils": "^0.2.5", "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", @@ -89,13 +92,13 @@ "start-server-and-test": "^1.10.11" }, "scripts": { - "start": "backstage-cli app:serve", - "build": "backstage-cli app:build", - "clean": "backstage-cli clean", - "test": "backstage-cli test", + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "test": "backstage-cli package test", "test:e2e": "start-server-and-test start http://localhost:3000 cy:dev", "test:e2e:ci": "start-server-and-test start http://localhost:3000 cy:run", - "lint": "backstage-cli lint", + "lint": "backstage-cli package lint", "cy:dev": "cypress open", "cy:run": "cypress run" }, diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 57f1fa536f..2441ace27b 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -34,10 +34,7 @@ import { Settings as SidebarSettings, UserSettingsSignInAvatar, } from '@backstage/plugin-user-settings'; -import { - SidebarSearchModal, - SearchContextProvider, -} from '@backstage/plugin-search'; +import { SidebarSearchModal } from '@backstage/plugin-search'; import { Shortcuts } from '@backstage/plugin-shortcuts'; import { Sidebar, @@ -89,9 +86,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( } to="/search"> - - - + }> diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index d4e60244d7..fe759c9799 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -24,7 +24,7 @@ import { SidebarPinStateContext, } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -import { CatalogResultListItem } from '@backstage/plugin-catalog'; +import { CatalogSearchResultListItem } from '@backstage/plugin-catalog'; import { catalogApiRef, CATALOG_FILTER_EXISTS, @@ -136,7 +136,7 @@ const SearchPage = () => { switch (type) { case 'software-catalog': return ( - diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 2e80c62c92..6a775b0d37 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/backend-common +## 0.10.9 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/cli-common@0.1.8 + - @backstage/config@0.1.15 + - @backstage/config-loader@0.9.5 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/types@0.1.3 + +## 0.10.8 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 +- b590e9b58d: Updated `isDatabaseConflictError` to handle modern sqlite conflict errors +- Updated dependencies + - @backstage/config-loader@0.9.4 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/cli-common@0.1.7 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.10.7 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 13a34a1d81..229134dffd 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.10.7", + "version": "0.10.8", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -11,6 +11,9 @@ "types": "dist/index.d.ts", "alphaTypes": "dist/index.alpha.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,21 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build --experimental-type-build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build --experimental-type-build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/cli-common": "^0.1.6", - "@backstage/config": "^0.1.13", - "@backstage/config-loader": "^0.9.3", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/types": "^0.1.1", + "@backstage/cli-common": "^0.1.7", + "@backstage/config": "^0.1.14", + "@backstage/config-loader": "^0.9.4", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/types": "^0.1.2", "@google-cloud/storage": "^5.8.0", "@manypkg/get-packages": "^1.1.3", "@octokit/rest": "^18.5.3", @@ -53,7 +57,7 @@ "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", "git-url-parse": "^11.6.0", - "helmet": "^4.0.0", + "helmet": "^5.0.2", "isomorphic-git": "^1.8.0", "jose": "^1.27.1", "keyv": "^4.0.3", @@ -84,8 +88,8 @@ } }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/archiver": "^5.1.0", "@types/compression": "^1.7.0", "@types/concat-stream": "^2.0.0", diff --git a/packages/backend-common/src/database/util.ts b/packages/backend-common/src/database/util.ts index 607554f294..a96eeb3a7b 100644 --- a/packages/backend-common/src/database/util.ts +++ b/packages/backend-common/src/database/util.ts @@ -27,7 +27,7 @@ export function isDatabaseConflictError(e: unknown) { return ( typeof message === 'string' && - (/SQLITE_CONSTRAINT: UNIQUE/.test(message) || + (/SQLITE_CONSTRAINT(?:_UNIQUE)?: UNIQUE/.test(message) || /unique constraint/.test(message)) ); } diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index d155287b34..105704159b 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -19,7 +19,7 @@ import compression from 'compression'; import cors from 'cors'; import express, { Router, ErrorRequestHandler } from 'express'; import helmet from 'helmet'; -import { ContentSecurityPolicyOptions } from 'helmet/dist/middlewares/content-security-policy'; +import { ContentSecurityPolicyOptions } from 'helmet/dist/types/middlewares/content-security-policy'; import * as http from 'http'; import stoppable from 'stoppable'; import { Logger } from 'winston'; @@ -215,8 +215,17 @@ export class ServiceBuilderImpl implements ServiceBuilder { httpsSettings: this.httpsSettings, helmetOptions: { contentSecurityPolicy: { + useDefaults: false, directives: applyCspDirectives(this.cspOptions), }, + // These are all disabled in order to maintain backwards compatibility + // when bumping helmet v5. We can't enable these by default because + // there is no way for users to configure them. + // TODO(Rugvip): We should give control of this setup to consumers + crossOriginEmbedderPolicy: false, + crossOriginOpenerPolicy: false, + crossOriginResourcePolicy: false, + originAgentCluster: false, }, }; } @@ -232,6 +241,11 @@ export function applyCspDirectives( // It should be replaced by any other solution that doesn't require unsafe-eval. result['script-src'] = ["'self'", "'unsafe-eval'"]; + // TODO(Rugvip): This is removed so that we maintained backwards compatibility + // when bumping to helmet v5, we could remove this as well as + // skip setting `useDefaults: false` in the future. + delete result['form-action']; + if (directives) { for (const [key, value] of Object.entries(directives)) { if (value === false) { diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index d611ee8ac1..1988c732a2 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/backend-tasks +## 0.1.8 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/types@0.1.3 + +## 0.1.7 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.1.6 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 364f1d1380..b84809ba69 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,18 +24,19 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/types": "^0.1.2", "@types/luxon": "^2.0.4", "knex": "^1.0.2", "lodash": "^4.17.21", @@ -43,8 +47,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/cli": "^0.13.2", + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/cli": "^0.14.0", "jest": "^26.0.1", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 55fb3c94cd..2ed22240bf 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/backend-test-utils +## 0.1.18 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/cli@0.14.0 + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 + ## 0.1.17 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 8a9767b292..a1471fbcf0 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.17", + "version": "0.1.18", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,17 +25,18 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/cli": "^0.13.2", - "@backstage/config": "^0.1.13", + "@backstage/backend-common": "^0.10.8", + "@backstage/cli": "^0.14.0", + "@backstage/config": "^0.1.14", "@vscode/sqlite3": "^5.0.7", "knex": "^1.0.2", "mysql2": "^2.2.5", @@ -41,7 +45,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "jest": "^26.0.1" }, "files": [ diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index d68ec80469..02014b41e1 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,84 @@ # example-backend +## 0.2.66 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/backend-tasks@0.1.8 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/integration@0.7.4 + - @backstage/plugin-app-backend@0.3.26 + - @backstage/plugin-auth-backend@0.10.2 + - @backstage/plugin-auth-node@0.1.2 + - @backstage/plugin-azure-devops-backend@0.3.5 + - @backstage/plugin-badges-backend@0.1.20 + - @backstage/plugin-catalog-backend@0.21.5 + - @backstage/plugin-code-coverage-backend@0.1.24 + - @backstage/plugin-graphql-backend@0.1.16 + - @backstage/plugin-jenkins-backend@0.1.15 + - @backstage/plugin-kafka-backend@0.2.19 + - @backstage/plugin-kubernetes-backend@0.4.9 + - @backstage/plugin-permission-backend@0.5.1 + - @backstage/plugin-permission-common@0.5.1 + - @backstage/plugin-permission-node@0.5.1 + - @backstage/plugin-proxy-backend@0.2.20 + - @backstage/plugin-rollbar-backend@0.1.23 + - @backstage/plugin-scaffolder-backend@0.16.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.3.1 + - @backstage/plugin-search-backend@0.4.4 + - @backstage/plugin-search-backend-module-elasticsearch@0.0.10 + - @backstage/plugin-search-backend-module-pg@0.2.8 + - @backstage/plugin-search-backend-node@0.4.7 + - @backstage/plugin-tech-insights-backend@0.2.6 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.10 + - @backstage/plugin-tech-insights-node@0.2.4 + - @backstage/plugin-techdocs-backend@0.13.5 + - @backstage/plugin-todo-backend@0.1.23 + +## 0.2.65 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-backend@0.13.4 + - @backstage/plugin-catalog-backend@0.21.4 + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/integration@0.7.3 + - @backstage/plugin-auth-backend@0.10.1 + - @backstage/plugin-auth-node@0.1.1 + - @backstage/plugin-permission-backend@0.5.0 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/plugin-rollbar-backend@0.1.22 + - @backstage/plugin-scaffolder-backend@0.16.0 + - @backstage/backend-tasks@0.1.7 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/plugin-app-backend@0.3.25 + - @backstage/plugin-azure-devops-backend@0.3.4 + - @backstage/plugin-badges-backend@0.1.19 + - @backstage/plugin-code-coverage-backend@0.1.23 + - @backstage/plugin-graphql-backend@0.1.15 + - @backstage/plugin-jenkins-backend@0.1.14 + - @backstage/plugin-kafka-backend@0.2.18 + - @backstage/plugin-kubernetes-backend@0.4.8 + - @backstage/plugin-permission-node@0.5.0 + - @backstage/plugin-proxy-backend@0.2.19 + - @backstage/plugin-scaffolder-backend-module-rails@0.3.0 + - @backstage/plugin-search-backend@0.4.3 + - @backstage/plugin-search-backend-module-elasticsearch@0.0.9 + - @backstage/plugin-search-backend-module-pg@0.2.7 + - @backstage/plugin-search-backend-node@0.4.6 + - @backstage/plugin-tech-insights-backend@0.2.5 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.9 + - @backstage/plugin-tech-insights-node@0.2.3 + - @backstage/plugin-todo-backend@0.1.22 + - example-app@0.2.65 + ## 0.2.64 ### Patch Changes diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 31231a3a4a..dd35d4ddbc 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -9,7 +9,7 @@ # # Once the commands have been run, you can build the image using `yarn build-image` -FROM node:14-buster-slim +FROM node:16-bullseye-slim WORKDIR /app @@ -19,6 +19,12 @@ WORKDIR /app COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz +# install sqlite3 dependencies +RUN apt-get update && \ + apt-get install -y libsqlite3-dev python3 cmake g++ && \ + rm -rf /var/lib/apt/lists/* && \ + yarn config set python /usr/bin/python3 + RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. diff --git a/packages/backend/package.json b/packages/backend/package.json index 35b234aeda..fe1908abc5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,10 +1,13 @@ { "name": "example-backend", - "version": "0.2.64", + "version": "0.2.65", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", "private": true, + "backstage": { + "role": "backend" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -15,48 +18,48 @@ "backstage" ], "scripts": { - "build": "backstage-cli backend:bundle", + "build": "backstage-cli package build", "build-image": "docker build ../.. -f Dockerfile --tag example-backend", - "start": "backstage-cli backend:dev", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "clean": "backstage-cli clean", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", "migrate:create": "knex migrate:make -x ts" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/backend-tasks": "^0.1.6", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-app-backend": "^0.3.24", - "@backstage/plugin-auth-backend": "^0.10.0", - "@backstage/plugin-auth-node": "^0.1.0", - "@backstage/plugin-azure-devops-backend": "^0.3.3", - "@backstage/plugin-badges-backend": "^0.1.18", - "@backstage/plugin-catalog-backend": "^0.21.3", - "@backstage/plugin-code-coverage-backend": "^0.1.22", - "@backstage/plugin-graphql-backend": "^0.1.14", - "@backstage/plugin-jenkins-backend": "^0.1.13", - "@backstage/plugin-kubernetes-backend": "^0.4.7", - "@backstage/plugin-kafka-backend": "^0.2.17", - "@backstage/plugin-permission-backend": "^0.4.3", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.3", - "@backstage/plugin-proxy-backend": "^0.2.18", - "@backstage/plugin-rollbar-backend": "^0.1.21", - "@backstage/plugin-scaffolder-backend": "^0.15.24", - "@backstage/plugin-scaffolder-backend-module-rails": "^0.2.6", - "@backstage/plugin-search-backend": "^0.4.2", - "@backstage/plugin-search-backend-node": "^0.4.5", - "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.8", - "@backstage/plugin-search-backend-module-pg": "^0.2.6", - "@backstage/plugin-techdocs-backend": "^0.13.3", - "@backstage/plugin-tech-insights-backend": "^0.2.4", - "@backstage/plugin-tech-insights-node": "^0.2.2", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.8", - "@backstage/plugin-todo-backend": "^0.1.21", + "@backstage/backend-common": "^0.10.8", + "@backstage/backend-tasks": "^0.1.7", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-app-backend": "^0.3.25", + "@backstage/plugin-auth-backend": "^0.10.1", + "@backstage/plugin-auth-node": "^0.1.1", + "@backstage/plugin-azure-devops-backend": "^0.3.4", + "@backstage/plugin-badges-backend": "^0.1.19", + "@backstage/plugin-catalog-backend": "^0.21.4", + "@backstage/plugin-code-coverage-backend": "^0.1.23", + "@backstage/plugin-graphql-backend": "^0.1.15", + "@backstage/plugin-jenkins-backend": "^0.1.14", + "@backstage/plugin-kubernetes-backend": "^0.4.8", + "@backstage/plugin-kafka-backend": "^0.2.18", + "@backstage/plugin-permission-backend": "^0.5.0", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-node": "^0.5.0", + "@backstage/plugin-proxy-backend": "^0.2.19", + "@backstage/plugin-rollbar-backend": "^0.1.22", + "@backstage/plugin-scaffolder-backend": "^0.16.0", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.3.0", + "@backstage/plugin-search-backend": "^0.4.3", + "@backstage/plugin-search-backend-node": "^0.4.6", + "@backstage/plugin-search-backend-module-elasticsearch": "^0.0.9", + "@backstage/plugin-search-backend-module-pg": "^0.2.7", + "@backstage/plugin-techdocs-backend": "^0.13.4", + "@backstage/plugin-tech-insights-backend": "^0.2.5", + "@backstage/plugin-tech-insights-node": "^0.2.3", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.9", + "@backstage/plugin-todo-backend": "^0.1.22", "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^18.5.3", "@vscode/sqlite3": "^5.0.7", @@ -73,7 +76,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5" diff --git a/packages/backend/src/plugins/permission.ts b/packages/backend/src/plugins/permission.ts index 276d16ff97..557cea9a26 100644 --- a/packages/backend/src/plugins/permission.ts +++ b/packages/backend/src/plugins/permission.ts @@ -35,8 +35,9 @@ class AllowAllPermissionPolicy implements PermissionPolicy { export default async function createPlugin( env: PluginEnvironment, ): Promise { - const { logger, discovery } = env; + const { logger, discovery, config } = env; return await createRouter({ + config, logger, discovery, policy: new AllowAllPermissionPolicy(), diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 664e7a49ed..ad3e03bbac 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/catalog-client +## 0.7.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/catalog-model@0.10.1 + - @backstage/errors@0.2.2 + +## 0.7.0 + +### Minor Changes + +- 8eda0e7a9c: **BREAKING**: Removed the explicit `DiscoveryApi` and `FetchApi` export symbols, + which were unnecessary duplicates from the well known core ones. + + The `CATALOG_FILTER_EXISTS` symbol's value has changed. However, this should not + affect any code in practice. + +- deaf6065db: Removed `CatalogApi.geLocationByEntity` and `CatalogApi.getOriginLocationByEntity`, and replaced them with `CatalogApi.getLocationByRef`. + + If you were using one of the two old methods, you can update your code as follows: + + ```diff + -const originLocation = catalogApi.getOriginLocationByEntity(entity); + +const originLocation = catalogApi.getLocationByRef(entity.metadata.annotations[ANNOTATION_ORIGIN_LOCATION]!); + -const location = catalogApi.getLocationByEntity(entity); + +const location = catalogApi.getLocationByRef(entity.metadata.annotations[ANNOTATION_LOCATION]!); + ``` + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- 244d24ebc4: Export the `Location` type that was previously exported by the `@backstage/catalog-model` package. +- 538ca90790: Deprecated the following types used by the catalog client, and created new + corresponding types to make them more consistent: + + - `CatalogEntitiesRequest` -> `GetEntitiesRequest` + - `CatalogListResponse` was removed and generally replaced with `GetEntitiesResponse` (which does not use a type parameter argument) + - `CatalogEntityAncestorsRequest`-> `GetEntityAncestorsRequest` + - `CatalogEntityAncestorsResponse` -> `GetEntityAncestorsResponse` + +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + ## 0.6.0 ### Minor Changes diff --git a/packages/catalog-client/api-report.md b/packages/catalog-client/api-report.md index 13b2e6b5f0..d5991303eb 100644 --- a/packages/catalog-client/api-report.md +++ b/packages/catalog-client/api-report.md @@ -5,7 +5,7 @@ ```ts import { Entity } from '@backstage/catalog-model'; import { EntityName } from '@backstage/catalog-model'; -import { Location as Location_2 } from '@backstage/catalog-model'; +import { LocationSpec } from '@backstage/catalog-model'; // @public export type AddLocationRequest = { @@ -32,27 +32,27 @@ export interface CatalogApi { options?: CatalogRequestOptions, ): Promise; getEntities( - request?: CatalogEntitiesRequest, + request?: GetEntitiesRequest, options?: CatalogRequestOptions, - ): Promise>; + ): Promise; getEntityAncestors( - request: CatalogEntityAncestorsRequest, + request: GetEntityAncestorsRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; getEntityByName( name: EntityName, options?: CatalogRequestOptions, ): Promise; - getLocationByEntity( - entity: Entity, + getEntityFacets( + request: GetEntityFacetsRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; getLocationById( id: string, options?: CatalogRequestOptions, ): Promise; - getOriginLocationByEntity( - entity: Entity, + getLocationByRef( + locationRef: string, options?: CatalogRequestOptions, ): Promise; refreshEntity( @@ -71,23 +71,35 @@ export interface CatalogApi { // @public export class CatalogClient implements CatalogApi { - constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi }); + constructor(options: { + discoveryApi: { + getBaseUrl(pluginId: string): Promise; + }; + fetchApi?: { + fetch: typeof fetch; + }; + }); addLocation( { type, target, dryRun, presence }: AddLocationRequest, options?: CatalogRequestOptions, ): Promise; getEntities( - request?: CatalogEntitiesRequest, + request?: GetEntitiesRequest, options?: CatalogRequestOptions, - ): Promise>; + ): Promise; getEntityAncestors( - request: CatalogEntityAncestorsRequest, + request: GetEntityAncestorsRequest, options?: CatalogRequestOptions, - ): Promise; + ): Promise; getEntityByName( compoundName: EntityName, options?: CatalogRequestOptions, ): Promise; + getEntityFacets( + request: GetEntityFacetsRequest, + options?: CatalogRequestOptions, + ): Promise; + // @deprecated (undocumented) getLocationByEntity( entity: Entity, options?: CatalogRequestOptions, @@ -96,6 +108,11 @@ export class CatalogClient implements CatalogApi { id: string, options?: CatalogRequestOptions, ): Promise; + getLocationByRef( + locationRef: string, + options?: CatalogRequestOptions, + ): Promise; + // @deprecated (undocumented) getOriginLocationByEntity( entity: Entity, options?: CatalogRequestOptions, @@ -114,53 +131,86 @@ export class CatalogClient implements CatalogApi { ): Promise; } -// @public -export type CatalogEntitiesRequest = { - filter?: - | Record[] - | Record - | undefined; - fields?: string[] | undefined; - offset?: number; - limit?: number; - after?: string; -}; +// @public @deprecated (undocumented) +export type CatalogEntitiesRequest = GetEntitiesRequest; + +// @public @deprecated (undocumented) +export type CatalogEntityAncestorsRequest = GetEntityAncestorsRequest; + +// @public @deprecated (undocumented) +export type CatalogEntityAncestorsResponse = GetEntityAncestorsResponse; + +// @public @deprecated (undocumented) +export type CatalogListResponse<_Entity> = GetEntitiesResponse; // @public -export type CatalogEntityAncestorsRequest = { - entityRef: string; -}; - -// @public -export type CatalogEntityAncestorsResponse = { - rootEntityRef: string; - items: { - entity: Entity; - parentEntityRefs: string[]; - }[]; -}; - -// @public -export type CatalogListResponse = { - items: T[]; -}; - -// @public -export type CatalogRequestOptions = { +export interface CatalogRequestOptions { + // (undocumented) token?: string; -}; - -// @public -export type DiscoveryApi = { - getBaseUrl(pluginId: string): Promise; -}; +} // @public export const ENTITY_STATUS_CATALOG_PROCESSING_TYPE = 'backstage.io/catalog-processing'; // @public -export type FetchApi = { - fetch: typeof fetch; -}; +export interface GetEntitiesRequest { + after?: string; + fields?: string[] | undefined; + filter?: + | Record[] + | Record + | undefined; + limit?: number; + offset?: number; +} + +// @public +export interface GetEntitiesResponse { + // (undocumented) + items: Entity[]; +} + +// @public +export interface GetEntityAncestorsRequest { + // (undocumented) + entityRef: string; +} + +// @public +export interface GetEntityAncestorsResponse { + // (undocumented) + items: Array<{ + entity: Entity; + parentEntityRefs: string[]; + }>; + // (undocumented) + rootEntityRef: string; +} + +// @public +export interface GetEntityFacetsRequest { + facets: string[]; + filter?: + | Record[] + | Record + | undefined; +} + +// @public +export interface GetEntityFacetsResponse { + facets: Record< + string, + Array<{ + value: string; + count: number; + }> + >; +} + +// @public +type Location_2 = { + id: string; +} & LocationSpec; +export { Location_2 as Location }; ``` diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 3a45a74680..40b6f238a8 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "0.6.0", + "version": "0.7.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,20 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/errors": "^0.2.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/errors": "^0.2.1", "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "msw": "^0.35.0" }, diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 1331f8e874..0035691f2c 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -18,7 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { CatalogClient } from './CatalogClient'; -import { CATALOG_FILTER_EXISTS, CatalogListResponse } from './types/api'; +import { CATALOG_FILTER_EXISTS, GetEntitiesResponse } from './types/api'; import { DiscoveryApi } from './types/discovery'; const server = setupServer(); @@ -60,7 +60,7 @@ describe('CatalogClient', () => { }, }, ]; - const defaultResponse: CatalogListResponse = { + const defaultResponse: GetEntitiesResponse = { items: defaultServiceResponse.reverse(), }; diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index a446d249c0..bb3c9604b3 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -15,14 +15,13 @@ */ import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, Entity, EntityName, - Location, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, parseEntityRef, stringifyEntityRef, - stringifyLocationReference, + stringifyLocationRef, } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; import crossFetch from 'cross-fetch'; @@ -31,43 +30,43 @@ import { AddLocationRequest, AddLocationResponse, CatalogApi, - CatalogEntitiesRequest, - CatalogListResponse, + GetEntitiesRequest, + GetEntitiesResponse, CatalogRequestOptions, - CatalogEntityAncestorsRequest, - CatalogEntityAncestorsResponse, + GetEntityAncestorsRequest, + GetEntityAncestorsResponse, + Location, + GetEntityFacetsRequest, + GetEntityFacetsResponse, } from './types/api'; import { DiscoveryApi } from './types/discovery'; import { FetchApi } from './types/fetch'; /** - * A frontend and backend compatible client for communicating with the Backstage Catalog. + * A frontend and backend compatible client for communicating with the Backstage + * software catalog. * * @public - * */ + */ export class CatalogClient implements CatalogApi { private readonly discoveryApi: DiscoveryApi; private readonly fetchApi: FetchApi; - constructor(options: { discoveryApi: DiscoveryApi; fetchApi?: FetchApi }) { + constructor(options: { + discoveryApi: { getBaseUrl(pluginId: string): Promise }; + fetchApi?: { fetch: typeof fetch }; + }) { this.discoveryApi = options.discoveryApi; this.fetchApi = options.fetchApi || { fetch: crossFetch }; } /** - * Gets the Ancestors of an Entity. - * - * @param request - A request type for retrieving Entity ancestors. - * @param options - An object with your preferred options. - * - * @returns A CatalogEntityAncestorsResponse. - * - * @public + * {@inheritdoc CatalogApi.getEntityAncestors} */ async getEntityAncestors( - request: CatalogEntityAncestorsRequest, + request: GetEntityAncestorsRequest, options?: CatalogRequestOptions, - ): Promise { + ): Promise { const { kind, namespace, name } = parseEntityRef(request.entityRef); return await this.requestRequired( 'GET', @@ -79,14 +78,7 @@ export class CatalogClient implements CatalogApi { } /** - * Gets a Location by Id. - * - * @param id - A string containing the Id. - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - * - * @public + * {@inheritdoc CatalogApi.getLocationById} */ async getLocationById( id: string, @@ -100,28 +92,20 @@ export class CatalogClient implements CatalogApi { } /** - * Gets a set of Entities. - * - * @param request - A request type for retrieving an Entity. - * @param options - An object with your preferred options. - * - * @returns A CatalogListResponse. - * - * @public + * {@inheritdoc CatalogApi.getEntities} */ async getEntities( - request?: CatalogEntitiesRequest, + request?: GetEntitiesRequest, options?: CatalogRequestOptions, - ): Promise> { + ): Promise { const { filter = [], fields = [], offset, limit, after } = request ?? {}; - const filterItems = [filter].flat(); const params: string[] = []; // filter param can occur multiple times, for example // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters // the "inner array" defined within a `filter` param corresponds to "allOf" filters - for (const filterItem of filterItems) { + for (const filterItem of [filter].flat()) { const filterParts: string[] = []; for (const [key, value] of Object.entries(filterItem)) { for (const v of [value].flat()) { @@ -187,14 +171,7 @@ export class CatalogClient implements CatalogApi { } /** - * Gets a given Entity based on a provided name. - * - * @param compoundName - A string containing the name. - * @param options - An object with your preferred options. - * - * @returns An {@link catalog-model#Entity}. - * - * @public + * {@inheritdoc CatalogApi.getEntityByName} */ async getEntityByName( compoundName: EntityName, @@ -211,12 +188,7 @@ export class CatalogClient implements CatalogApi { } /** - * Refreshes an Entity. - * - * @param entityRef - A string containing the entityREf - * @param options - An object with your preferred options. - * - * @public + * {@inheritdoc CatalogApi.refreshEntity} */ async refreshEntity(entityRef: string, options?: CatalogRequestOptions) { const response = await this.fetchApi.fetch( @@ -237,14 +209,48 @@ export class CatalogClient implements CatalogApi { } /** - * Adds a location. - * - * @param options - An object with your preferred options. - * @param AddLocationRequest - A request object for adding locations. - * - * @returns An AddLocationResponse - * - * @public + * {@inheritdoc CatalogApi.getEntityFacets} + */ + async getEntityFacets( + request: GetEntityFacetsRequest, + options?: CatalogRequestOptions, + ): Promise { + const { filter = [], facets } = request; + const params: string[] = []; + + // filter param can occur multiple times, for example + // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' + // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters + // the "inner array" defined within a `filter` param corresponds to "allOf" filters + for (const filterItem of [filter].flat()) { + const filterParts: string[] = []; + for (const [key, value] of Object.entries(filterItem)) { + for (const v of [value].flat()) { + if (v === CATALOG_FILTER_EXISTS) { + filterParts.push(encodeURIComponent(key)); + } else if (typeof v === 'string') { + filterParts.push( + `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, + ); + } + } + } + + if (filterParts.length) { + params.push(`filter=${filterParts.join(',')}`); + } + } + + for (const facet of facets) { + params.push(`facet=${encodeURIComponent(facet)}`); + } + + const query = params.length ? `?${params.join('&')}` : ''; + return await this.requestOptional('GET', `/entity-facets${query}`, options); + } + + /** + * {@inheritdoc CatalogApi.addLocation} */ async addLocation( { type = 'url', target, dryRun, presence }: AddLocationRequest, @@ -282,21 +288,14 @@ export class CatalogClient implements CatalogApi { } /** - * Gets an origin Location By Entity. - * - * @param entity - An Entity - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - * - * @public + * @deprecated please use getLocationByRef instead */ async getOriginLocationByEntity( entity: Entity, options?: CatalogRequestOptions, ): Promise { const locationCompound = - entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION]; + entity.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION]; if (!locationCompound) { return undefined; } @@ -307,24 +306,17 @@ export class CatalogClient implements CatalogApi { ); return all .map(r => r.data) - .find(l => locationCompound === stringifyLocationReference(l)); + .find(l => locationCompound === stringifyLocationRef(l)); } /** - * Gets a Location by Entity. - * - * @param entity - An Entity - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - * - * @public + * @deprecated please use getLocationByRef instead */ async getLocationByEntity( entity: Entity, options?: CatalogRequestOptions, ): Promise { - const locationCompound = entity.metadata.annotations?.[LOCATION_ANNOTATION]; + const locationCompound = entity.metadata.annotations?.[ANNOTATION_LOCATION]; if (!locationCompound) { return undefined; } @@ -335,16 +327,28 @@ export class CatalogClient implements CatalogApi { ); return all .map(r => r.data) - .find(l => locationCompound === stringifyLocationReference(l)); + .find(l => locationCompound === stringifyLocationRef(l)); } /** - * Removes a location as identified by Id. - * - * @param id - A string containing the Id - * @param options - An object with your preferred options. - * - * @public + * {@inheritdoc CatalogApi.getLocationByRef} + */ + async getLocationByRef( + locationRef: string, + options?: CatalogRequestOptions, + ): Promise { + const all: { data: Location }[] = await this.requestRequired( + 'GET', + '/locations', + options, + ); + return all + .map(r => r.data) + .find(l => locationRef === stringifyLocationRef(l)); + } + + /** + * {@inheritdoc CatalogApi.removeLocationById} */ async removeLocationById( id: string, @@ -358,12 +362,7 @@ export class CatalogClient implements CatalogApi { } /** - * Removes an Entity as identified by Uid. - * - * @param uid - A string containing the Uid - * @param options - An object with your preferred options. - * - * @public + * {@inheritdoc CatalogApi.removeEntityByUid} */ async removeEntityByUid( uid: string, diff --git a/packages/catalog-client/src/types/api.ts b/packages/catalog-client/src/types/api.ts index 0622d654fa..b070820c8b 100644 --- a/packages/catalog-client/src/types/api.ts +++ b/packages/catalog-client/src/types/api.ts @@ -14,21 +14,26 @@ * limitations under the License. */ -import { Entity, EntityName, Location } from '@backstage/catalog-model'; +import { Entity, EntityName, LocationSpec } from '@backstage/catalog-model'; /** - * A Symbol to define if a catalog filter exists or not. + * This symbol can be used in place of a value when passed to filters in e.g. + * {@link CatalogClient.getEntities}, to signify that you want to filter on the + * presence of that key no matter what its value is. * * @public */ -export const CATALOG_FILTER_EXISTS = Symbol('CATALOG_FILTER_EXISTS'); +export const CATALOG_FILTER_EXISTS = Symbol.for( + // Random UUID to ensure no collisions + 'CATALOG_FILTER_EXISTS_0e15b590c0b343a2bae3e787e84c2111', +); /** - * A request type for retrieving catalog Entities. + * The request type for {@link CatalogClient.getEntities}. * * @public */ -export type CatalogEntitiesRequest = { +export interface GetEntitiesRequest { /** * If given, return only entities that match the given patterns. * @@ -104,175 +109,143 @@ export type CatalogEntitiesRequest = { * request. */ after?: string; -}; +} /** - * A request type for Catalog Entity Ancestor information. + * The response type for {@link CatalogClient.getEntities}. * * @public */ -export type CatalogEntityAncestorsRequest = { +export interface GetEntitiesResponse { + items: Entity[]; +} + +/** + * The request type for {@link CatalogClient.getEntityAncestors}. + * + * @public + */ +export interface GetEntityAncestorsRequest { entityRef: string; -}; +} /** - * A response type for Catalog Entity Ancestor information. + * The response type for {@link CatalogClient.getEntityAncestors}. * * @public */ -export type CatalogEntityAncestorsResponse = { +export interface GetEntityAncestorsResponse { rootEntityRef: string; - items: { entity: Entity; parentEntityRefs: string[] }[]; -}; + items: Array<{ + entity: Entity; + parentEntityRefs: string[]; + }>; +} /** - * A response type for the result of a catalog operation in list form. + * The request type for {@link CatalogClient.getEntityFacets}. * * @public */ -export type CatalogListResponse = { - items: T[]; -}; +export interface GetEntityFacetsRequest { + /** + * If given, return only entities that match the given patterns. + * + * @remarks + * + * If multiple filter sets are given as an array, then there is effectively an + * OR between each filter set. + * + * Within one filter set, there is effectively an AND between the various + * keys. + * + * Within one key, if there are more than one value, then there is effectively + * an OR between them. + * + * Example: For an input of + * + * ``` + * [ + * { kind: ['API', 'Component'] }, + * { 'metadata.name': 'a', 'metadata.namespace': 'b' } + * ] + * ``` + * + * This effectively means + * + * ``` + * (kind = EITHER 'API' OR 'Component') + * OR + * (metadata.name = 'a' AND metadata.namespace = 'b' ) + * ``` + * + * Each key is a dot separated path in each object. + * + * As a value you can also pass in the symbol `CATALOG_FILTER_EXISTS` + * (exported from this package), which means that you assert on the existence + * of that key, no matter what its value is. + */ + filter?: + | Record[] + | Record + | undefined; + /** + * Dot separated paths for the facets to extract from each entity. + * + * @remarks + * + * Example: For an input of `['kind', 'metadata.annotations.backstage.io/orphan']`, then the + * response will be shaped like + * + * ``` + * { + * "facets": { + * "kind": [ + * { "key": "Component", "count": 22 }, + * { "key": "API", "count": 13 } + * ], + * "metadata.annotations.backstage.io/orphan": [ + * { "key": "true", "count": 2 } + * ] + * } + * } + * ``` + */ + facets: string[]; +} + +/** + * The response type for {@link CatalogClient.getEntityFacets}. + * + * @public + */ +export interface GetEntityFacetsResponse { + /** + * The computed facets, one entry per facet in the request. + */ + facets: Record>; +} /** * Options you can pass into a catalog request for additional information. * * @public */ -export type CatalogRequestOptions = { +export interface CatalogRequestOptions { token?: string; -}; - -/** - * Public functions for interacting with the Catalog API. - * - * @public - */ -export interface CatalogApi { - /** - * Gets the Entities from the catalog based on your request and options. - * - * @param request - An object with your filters and fields. - * @param options - An object with your preferred options. - * - * @returns A CatalogListResponse with items typed Catalog Model Entity. - * - */ - getEntities( - request?: CatalogEntitiesRequest, - options?: CatalogRequestOptions, - ): Promise>; - /** - * Gets the Entity ancestor information from the catalog based on your request and options. - * - * @param request - An object with your filters and fields. - * @param options - An object with your preferred options. - * - * @returns A CatalogEntityAncestorsResponse. - */ - getEntityAncestors( - request: CatalogEntityAncestorsRequest, - options?: CatalogRequestOptions, - ): Promise; - /** - * Gets a single Entity from the catalog by Entity name. - * - * @param name - A complete Entity name, with the full kind-namespace-name triplet. - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Entity}. - */ - getEntityByName( - name: EntityName, - options?: CatalogRequestOptions, - ): Promise; - /** - * Removes a single Entity from the catalog by Entity UID. - * - * @param uid - A string of the Entity UID. - * @param options - An object with your preferred options. - * - */ - removeEntityByUid( - uid: string, - options?: CatalogRequestOptions, - ): Promise; - /** - * Refreshes an Entity in the catalog. - * - * @param entityRef - A string in the form of 'Kind/default:foo'. - * @param options - An object with your preferred options. - * - */ - refreshEntity( - entityRef: string, - options?: CatalogRequestOptions, - ): Promise; - - // Locations - /** - * Gets a Location object by ID from the catalog. - * - * @param id - A string in of the Location Id. - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - */ - getLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise; - /** - * Gets origin location by Entity. - * - * @param entity - An {@link catalog-model#Entity}. - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - */ - getOriginLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise; - /** - * Gets Location by Entity. - * - * @param entity - An {@link catalog-model#Entity}. - * @param options - An object with your preferred options. - * - * @returns A {@link catalog-model#Location_2}. - */ - getLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise; - /** - * Adds a Location. - * - * @param location - A request type for adding a Location to the catalog. - * @param options - An object with your preferred options. - * - * @returns A AddLocationResponse. - */ - addLocation( - location: AddLocationRequest, - options?: CatalogRequestOptions, - ): Promise; - /** - * Removes a Location by Id. - * - * @param id - A string in of the Location Id. - * @param options - An object with your preferred options. - * - */ - removeLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise; } /** - * A request type for adding a Location to the catalog. + * Entity location for a specific entity. + * + * @public + */ +export type Location = { + id: string; +} & LocationSpec; + +/** + * The request type for {@link CatalogClient.addLocation}. * * @public */ @@ -284,13 +257,135 @@ export type AddLocationRequest = { }; /** - * A response type for adding a Location to the catalog. + * The response type for {@link CatalogClient.addLocation}. * * @public */ export type AddLocationResponse = { location: Location; entities: Entity[]; - // Exists is only set in DryRun mode. + // Only set in dryRun mode. exists?: boolean; }; + +/** + * A client for interacting with the Backstage software catalog through its API. + * + * @public + */ +export interface CatalogApi { + /** + * Lists catalog entities. + * + * @param request - Request parameters + * @param options - Additional options + */ + getEntities( + request?: GetEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Gets entity ancestor information, i.e. the hierarchy of parent entities + * whose processing resulted in a given entity appearing in the catalog. + * + * @param request - Request parameters + * @param options - Additional options + */ + getEntityAncestors( + request: GetEntityAncestorsRequest, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Gets a single entity from the catalog by its ref (kind, namespace, name) + * triplet. + * + * @param name - A complete entity ref + * @param options - Additional options + */ + getEntityByName( + name: EntityName, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Removes a single entity from the catalog by entity UID. + * + * @param uid - An entity UID + * @param options - Additional options + */ + removeEntityByUid( + uid: string, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Refreshes (marks for reprocessing) an entity in the catalog. + * + * @param entityRef - An entity ref on string form (e.g. + * 'component/default:my-component') + * @param options - Additional options + */ + refreshEntity( + entityRef: string, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Gets a summary of field facets of entities in the catalog. + * + * @param request - Request parameters + * @param options - Additional options + */ + getEntityFacets( + request: GetEntityFacetsRequest, + options?: CatalogRequestOptions, + ): Promise; + + // Locations + + /** + * Gets a registered location by its ID. + * + * @param id - A location ID + * @param options - Additional options + */ + getLocationById( + id: string, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Gets a registered location by its ref. + * + * @param locationRef - A location ref, e.g. "url:https://github.com/..." + * @param options - Additional options + */ + getLocationByRef( + locationRef: string, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Registers a new location. + * + * @param location - Request parameters + * @param options - Additional options + */ + addLocation( + location: AddLocationRequest, + options?: CatalogRequestOptions, + ): Promise; + + /** + * Removes a registered Location by its ID. + * + * @param id - A location ID + * @param options - Additional options + */ + removeLocationById( + id: string, + options?: CatalogRequestOptions, + ): Promise; +} diff --git a/packages/catalog-client/src/types/deprecated.ts b/packages/catalog-client/src/types/deprecated.ts new file mode 100644 index 0000000000..0b145f3024 --- /dev/null +++ b/packages/catalog-client/src/types/deprecated.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { + GetEntitiesRequest, + GetEntitiesResponse, + GetEntityAncestorsRequest, + GetEntityAncestorsResponse, +} from './api'; + +/** + * @public + * @deprecated use GetEntitiesRequest instead + */ +export type CatalogEntitiesRequest = GetEntitiesRequest; +/** + * @public + * @deprecated use GetEntitiesResponse instead + */ +export type CatalogListResponse<_Entity> = GetEntitiesResponse; +/** + * @public + * @deprecated use GetEntityAncestorsRequest instead + */ +export type CatalogEntityAncestorsRequest = GetEntityAncestorsRequest; +/** + * @public + * @deprecated use GetEntityAncestorsResponse instead + */ +export type CatalogEntityAncestorsResponse = GetEntityAncestorsResponse; diff --git a/packages/catalog-client/src/types/discovery.ts b/packages/catalog-client/src/types/discovery.ts index 5fa14372e3..19f304b1fd 100644 --- a/packages/catalog-client/src/types/discovery.ts +++ b/packages/catalog-client/src/types/discovery.ts @@ -16,8 +16,6 @@ /** * This is a copy of the DiscoveryApi, to avoid importing core-plugin-api. - * - * @public */ export type DiscoveryApi = { getBaseUrl(pluginId: string): Promise; diff --git a/packages/catalog-client/src/types/fetch.ts b/packages/catalog-client/src/types/fetch.ts index 59de6a68f1..047a9f3558 100644 --- a/packages/catalog-client/src/types/fetch.ts +++ b/packages/catalog-client/src/types/fetch.ts @@ -16,8 +16,6 @@ /** * This is a copy of FetchApi, to avoid importing core-plugin-api. - * - * @public */ export type FetchApi = { fetch: typeof fetch; diff --git a/packages/catalog-client/src/types/index.ts b/packages/catalog-client/src/types/index.ts index f3c6fab4e9..39c8962b68 100644 --- a/packages/catalog-client/src/types/index.ts +++ b/packages/catalog-client/src/types/index.ts @@ -14,17 +14,19 @@ * limitations under the License. */ +export { CATALOG_FILTER_EXISTS } from './api'; export type { AddLocationRequest, AddLocationResponse, CatalogApi, - CatalogEntitiesRequest, - CatalogListResponse, CatalogRequestOptions, - CatalogEntityAncestorsRequest, - CatalogEntityAncestorsResponse, + GetEntitiesRequest, + GetEntitiesResponse, + GetEntityAncestorsRequest, + GetEntityAncestorsResponse, + Location, + GetEntityFacetsRequest, + GetEntityFacetsResponse, } from './api'; -export type { DiscoveryApi } from './discovery'; -export type { FetchApi } from './fetch'; -export { CATALOG_FILTER_EXISTS } from './api'; +export * from './deprecated'; export { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from './status'; diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 9dbf2f116b..07d00f25ea 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/catalog-model +## 0.10.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/types@0.1.3 + +## 0.10.0 + +### Minor Changes + +- e483dd6c72: **BREAKING**: Remove deprecated validation methods `analyzeLocationSchema`, `locationSchema` and `locationSpecSchema`. + This functionality was primarily used internally by the `catalog-backend`. +- edbc03814a: **BREAKING**: Remove deprecated `serializeEntityRef` which is replaced by `stringifyEntityRef`. +- e72d371296: **BREAKING**: Removed `TemplateEntityV1beta2` from the model and moved it to + `@backstage/plugin-scaffolder-common` where `TemplateEntityV1beta3` already + lived. It has also been marked as deprecated in the process - please consider + [migrating to `v1beta3` templates](https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3). + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 216725b434: Deprecated `parseLocationReference` and `stringifyLocationReference`, + introducing `parseLocationRef` and `stringifyLocationRef` in their place. +- 244d24ebc4: Deprecates the `Location` type export from this package. Imports of the `Location` type should now be done from the `@backstage/catalog-client` package instead. +- 7aeb491394: Deprecated `ENTITY_DEFAULT_NAMESPACE` constant in favour of `DEFAULT_NAMESPACE`. +- 0d03e42a89: Deprecated `compareEntityToRef` due to low usage and provided value. +- e8c6f9d282: Deprecated the `EntityRefContext` type which had limited use. +- 7f21538c9e: Deprecated `JSONSchema` export type. +- 20f3244102: Deprecates the following exports which all have very limited and internal use. `ENTITY_META_GENERATED_FIELDS`, `entityHasChanges`, `generateEntityEtag`, `generateEntityUid`, `generateUpdatedEntity`, `ENTITY_META_GENERATED_FIELDS`. +- 27eccab216: Deprecates `EDIT_URL_ANNOTATION`, `LOCATION_ANNOTATION`, `ORIGIN_LOCATION_ANNOTATION`, `SOURCE_LOCATION_ANNOTATION`, `VIEW_URL_ANNOTATION` + and replaces these constants all prefixed with ANNOTATION\_ `ANNOTATION_EDIT_URL`, `ANNOTATION_LOCATION`, `ANNOTATION_ORIGIN_LOCATION`, `ANNOTATION_SOURCE_LOCATION`, `ANNOTATION_VIEW_URL` +- Updated dependencies + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.9.10 ### Patch Changes diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index a0460fc4f2..0afe87e709 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -7,17 +7,27 @@ import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { SerializedError } from '@backstage/errors'; -import * as yup from 'yup'; // @alpha export interface AlphaEntity extends Entity { status?: EntityStatus; } -// @public @deprecated -export const analyzeLocationSchema: yup.SchemaOf<{ - location: LocationSpec; -}>; +// @public +export const ANNOTATION_EDIT_URL = 'backstage.io/edit-url'; + +// @public +export const ANNOTATION_LOCATION = 'backstage.io/managed-by-location'; + +// @public +export const ANNOTATION_ORIGIN_LOCATION = + 'backstage.io/managed-by-origin-location'; + +// @public +export const ANNOTATION_SOURCE_LOCATION = 'backstage.io/source-location'; + +// @public +export const ANNOTATION_VIEW_URL = 'backstage.io/view-url'; // @public interface ApiEntityV1alpha1 extends Entity { @@ -56,11 +66,14 @@ export class CommonValidatorFunctions { static isValidUrl(value: unknown): boolean; } -// @public +// @public @deprecated export function compareEntityToRef( entity: Entity, ref: EntityRef | EntityName, - context?: EntityRefContext, + context?: { + defaultKind?: string; + defaultNamespace?: string; + }, ): boolean; // @public @@ -87,6 +100,9 @@ export { ComponentEntityV1alpha1 }; // @public export const componentEntityV1alpha1Validator: KindValidator; +// @public +export const DEFAULT_NAMESPACE = 'default'; + // @public export class DefaultNamespaceEntityPolicy implements EntityPolicy { constructor(namespace?: string); @@ -111,7 +127,7 @@ export { DomainEntityV1alpha1 }; // @public export const domainEntityV1alpha1Validator: KindValidator; -// @public +// @public @deprecated export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url'; // @public @@ -123,10 +139,10 @@ export type Entity = { relations?: EntityRelation[]; }; -// @public +// @public @deprecated export const ENTITY_DEFAULT_NAMESPACE = 'default'; -// @public +// @public @deprecated export const ENTITY_META_GENERATED_FIELDS: readonly [ 'uid', 'etag', @@ -148,7 +164,7 @@ export function entityEnvelopeSchemaValidator< T extends EntityEnvelope = EntityEnvelope, >(schema?: unknown): (data: unknown) => T; -// @public +// @public @deprecated export function entityHasChanges(previous: Entity, next: Entity): boolean; // @public @@ -205,7 +221,7 @@ export type EntityRef = name: string; }; -// @public +// @public @deprecated export type EntityRefContext = { defaultKind?: string; defaultNamespace?: string; @@ -217,13 +233,6 @@ export type EntityRelation = { target: EntityName; }; -// @public -export type EntityRelationSpec = { - source: EntityName; - type: string; - target: EntityName; -}; - // @public export function entitySchemaValidator( schema?: unknown, @@ -252,13 +261,13 @@ export class FieldFormatEntityPolicy implements EntityPolicy { enforce(entity: Entity): Promise; } -// @public +// @public @deprecated export function generateEntityEtag(): string; -// @public +// @public @deprecated export function generateEntityUid(): string; -// @public +// @public @deprecated export function generateUpdatedEntity(previous: Entity, next: Entity): Entity; // @public @@ -295,7 +304,7 @@ export { GroupEntityV1alpha1 }; // @public export const groupEntityV1alpha1Validator: KindValidator; -// @public +// @public @deprecated export type JSONSchema = JSONSchema7 & { [key in string]?: JsonValue; }; @@ -325,13 +334,13 @@ export class KubernetesValidatorFunctions { static isValidObjectName(value: unknown): boolean; } -// @public +// @public @deprecated type Location_2 = { id: string; } & LocationSpec; export { Location_2 as Location }; -// @public +// @public @deprecated export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location'; // @public @@ -354,9 +363,6 @@ export { LocationEntityV1alpha1 }; // @public export const locationEntityV1alpha1Validator: KindValidator; -// @public @deprecated -export const locationSchema: yup.SchemaOf; - // @public export type LocationSpec = { type: string; @@ -364,9 +370,6 @@ export type LocationSpec = { presence?: 'optional' | 'required'; }; -// @public @deprecated -export const locationSpecSchema: yup.SchemaOf; - // @public export function makeValidator(overrides?: Partial): Validators; @@ -377,14 +380,17 @@ export class NoForeignRootFieldsEntityPolicy implements EntityPolicy { enforce(entity: Entity): Promise; } -// @public +// @public @deprecated export const ORIGIN_LOCATION_ANNOTATION = 'backstage.io/managed-by-origin-location'; // @public export function parseEntityName( ref: EntityRef, - context?: EntityRefContext, + context?: { + defaultKind?: string; + defaultNamespace?: string; + }, ): EntityName; // @public @@ -421,6 +427,12 @@ export function parseEntityRef( }; // @public +export function parseLocationRef(ref: string): { + type: string; + target: string; +}; + +// @public @deprecated export function parseLocationReference(ref: string): { type: string; target: string; @@ -496,17 +508,6 @@ export class SchemaValidEntityPolicy implements EntityPolicy { } // @public @deprecated -export function serializeEntityRef( - ref: - | Entity - | { - kind?: string; - namespace?: string; - name: string; - }, -): EntityRef; - -// @public export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location'; // @public @@ -521,6 +522,12 @@ export function stringifyEntityRef( ): string; // @public +export function stringifyLocationRef(ref: { + type: string; + target: string; +}): string; + +// @public @deprecated export function stringifyLocationReference(ref: { type: string; target: string; @@ -544,33 +551,6 @@ export { SystemEntityV1alpha1 }; // @public export const systemEntityV1alpha1Validator: KindValidator; -// @public -export interface TemplateEntityV1beta2 extends Entity { - // (undocumented) - apiVersion: 'backstage.io/v1beta2'; - // (undocumented) - kind: 'Template'; - // (undocumented) - spec: { - type: string; - parameters?: JsonObject | JsonObject[]; - steps: Array<{ - id?: string; - name?: string; - action: string; - input?: JsonObject; - if?: string | boolean; - }>; - output?: { - [name: string]: string; - }; - owner?: string; - }; -} - -// @public -export const templateEntityV1beta2Validator: KindValidator; - // @public interface UserEntityV1alpha1 extends Entity { // (undocumented) @@ -606,6 +586,6 @@ export type Validators = { isValidTag(value: unknown): boolean; }; -// @public +// @public @deprecated export const VIEW_URL_ANNOTATION = 'backstage.io/view-url'; ``` diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index efe32cccff..a34449f38d 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "0.9.10", + "version": "0.10.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -13,6 +13,9 @@ "types": "dist/index.d.ts", "alphaTypes": "dist/index.alpha.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -23,27 +26,25 @@ "backstage" ], "scripts": { - "build": "backstage-cli build --experimental-type-build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build --experimental-type-build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/types": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/types": "^0.1.2", "@types/json-schema": "^7.0.5", - "@types/yup": "^0.29.13", "ajv": "^7.0.3", "json-schema": "^0.4.0", "lodash": "^4.17.21", - "uuid": "^8.0.0", - "yup": "^0.32.9" + "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "@types/lodash": "^4.14.151", "yaml": "^1.9.2" diff --git a/packages/catalog-model/src/entity/Entity.ts b/packages/catalog-model/src/entity/Entity.ts index f56774025c..7199334e51 100644 --- a/packages/catalog-model/src/entity/Entity.ts +++ b/packages/catalog-model/src/entity/Entity.ts @@ -201,28 +201,6 @@ export type EntityRelation = { target: EntityName; }; -/** - * Holds the relation data for entities. - * - * @public - */ -export type EntityRelationSpec = { - /** - * The source entity of this relation. - */ - source: EntityName; - - /** - * The type of the relation. - */ - type: string; - - /** - * The target entity of this relation. - */ - target: EntityName; -}; - /** * A link to external information that is related to the entity. * diff --git a/packages/catalog-model/src/entity/constants.ts b/packages/catalog-model/src/entity/constants.ts index 6daf6b78d9..6cef19cac9 100644 --- a/packages/catalog-model/src/entity/constants.ts +++ b/packages/catalog-model/src/entity/constants.ts @@ -18,13 +18,22 @@ * The namespace that entities without an explicit namespace fall into. * * @public + * @deprecated use {@link DEFAULT_NAMESPACE} instead. */ export const ENTITY_DEFAULT_NAMESPACE = 'default'; +/** + * The namespace that entities without an explicit namespace fall into. + * + * @public + */ +export const DEFAULT_NAMESPACE = 'default'; + /** * The keys of EntityMeta that are auto-generated. * * @public + * @deprecated will be removed in a future release. */ export const ENTITY_META_GENERATED_FIELDS = [ 'uid', @@ -36,6 +45,7 @@ export const ENTITY_META_GENERATED_FIELDS = [ * Annotation for linking to entity page from catalog pages. * * @public + * @deprecated use {@link ANNOTATION_VIEW_URL} instead. */ export const VIEW_URL_ANNOTATION = 'backstage.io/view-url'; @@ -43,5 +53,20 @@ export const VIEW_URL_ANNOTATION = 'backstage.io/view-url'; * Annotation for linking to entity edit page from catalog pages. * * @public + * @deprecated use {@link ANNOTATION_EDIT_URL} instead. */ export const EDIT_URL_ANNOTATION = 'backstage.io/edit-url'; + +/** + * Annotation for linking to entity page from catalog pages. + * + * @public + */ +export const ANNOTATION_VIEW_URL = 'backstage.io/view-url'; + +/** + * Annotation for linking to entity edit page from catalog pages. + * + * @public + */ +export const ANNOTATION_EDIT_URL = 'backstage.io/edit-url'; diff --git a/packages/catalog-model/src/entity/index.ts b/packages/catalog-model/src/entity/index.ts index ce1e76a20b..f619d0f39e 100644 --- a/packages/catalog-model/src/entity/index.ts +++ b/packages/catalog-model/src/entity/index.ts @@ -17,8 +17,11 @@ export { EDIT_URL_ANNOTATION, ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, ENTITY_META_GENERATED_FIELDS, VIEW_URL_ANNOTATION, + ANNOTATION_EDIT_URL, + ANNOTATION_VIEW_URL, } from './constants'; export type { AlphaEntity, @@ -26,7 +29,6 @@ export type { EntityLink, EntityMeta, EntityRelation, - EntityRelationSpec, } from './Entity'; export type { EntityEnvelope } from './EntityEnvelope'; export type { @@ -40,7 +42,6 @@ export { getEntityName, parseEntityName, parseEntityRef, - serializeEntityRef, stringifyEntityRef, } from './ref'; export type { EntityRefContext } from './ref'; diff --git a/packages/catalog-model/src/entity/ref.test.ts b/packages/catalog-model/src/entity/ref.test.ts index cf4bf0d869..f80b588d55 100644 --- a/packages/catalog-model/src/entity/ref.test.ts +++ b/packages/catalog-model/src/entity/ref.test.ts @@ -16,12 +16,7 @@ import { ENTITY_DEFAULT_NAMESPACE } from './constants'; import { Entity } from './Entity'; -import { - compareEntityToRef, - parseEntityName, - parseEntityRef, - serializeEntityRef, -} from './ref'; +import { compareEntityToRef, parseEntityName, parseEntityRef } from './ref'; describe('ref', () => { describe('parseEntityName', () => { @@ -329,64 +324,6 @@ describe('ref', () => { }); }); - describe('serializeEntityRef', () => { - it('handles partials', () => { - expect( - serializeEntityRef({ kind: 'a', namespace: 'b', name: 'c' }), - ).toEqual('a:b/c'); - expect(serializeEntityRef({ namespace: 'b', name: 'c' })).toEqual('b/c'); - expect(serializeEntityRef({ kind: 'a', name: 'c' })).toEqual('a:c'); - expect(serializeEntityRef({ name: 'c' })).toEqual('c'); - }); - - it('handles entities', () => { - const entityWithNamespace: Entity = { - apiVersion: 'a', - kind: 'b', - metadata: { - name: 'c', - namespace: 'd', - }, - }; - const entityWithoutNamespace: Entity = { - apiVersion: 'a', - kind: 'b', - metadata: { - name: 'c', - }, - }; - expect(serializeEntityRef(entityWithNamespace)).toEqual('b:d/c'); - expect(serializeEntityRef(entityWithoutNamespace)).toEqual('b:c'); - }); - - it('picks the least complex form', () => { - expect( - serializeEntityRef({ kind: 'a', namespace: 'b', name: 'c' }), - ).toEqual('a:b/c'); - expect(serializeEntityRef({ namespace: 'b', name: 'c' })).toEqual('b/c'); - expect(serializeEntityRef({ kind: 'a', name: 'c' })).toEqual('a:c'); - expect(serializeEntityRef({ name: 'c' })).toEqual('c'); - expect( - serializeEntityRef({ kind: 'a:x', namespace: 'b', name: 'c' }), - ).toEqual({ kind: 'a:x', namespace: 'b', name: 'c' }); - expect( - serializeEntityRef({ kind: 'a/x', namespace: 'b', name: 'c' }), - ).toEqual({ kind: 'a/x', namespace: 'b', name: 'c' }); - expect( - serializeEntityRef({ kind: 'a', namespace: 'b:x', name: 'c' }), - ).toEqual({ kind: 'a', namespace: 'b:x', name: 'c' }); - expect( - serializeEntityRef({ kind: 'a', namespace: 'b/x', name: 'c' }), - ).toEqual({ kind: 'a', namespace: 'b/x', name: 'c' }); - expect( - serializeEntityRef({ kind: 'a', namespace: 'b', name: 'c:x' }), - ).toEqual({ kind: 'a', namespace: 'b', name: 'c:x' }); - expect( - serializeEntityRef({ kind: 'a', namespace: 'b', name: 'c/x' }), - ).toEqual({ kind: 'a', namespace: 'b', name: 'c/x' }); - }); - }); - describe('compareEntityToRef', () => { const entityWithNamespace: Entity = { apiVersion: 'a', diff --git a/packages/catalog-model/src/entity/ref.ts b/packages/catalog-model/src/entity/ref.ts index 958f750e32..122fe0b31a 100644 --- a/packages/catalog-model/src/entity/ref.ts +++ b/packages/catalog-model/src/entity/ref.ts @@ -57,6 +57,7 @@ export function getEntityName(entity: Entity): EntityName { * The context of defaults that entity reference parsing happens within. * * @public + * @deprecated type inlined, will be removed in a future release. */ export type EntityRefContext = { /** The default kind, if none is given in the reference */ @@ -82,7 +83,12 @@ export type EntityRefContext = { */ export function parseEntityName( ref: EntityRef, - context: EntityRefContext = {}, + context: { + /** The default kind, if none is given in the reference */ + defaultKind?: string; + /** The default namespace, if none is given in the reference */ + defaultNamespace?: string; + } = {}, ): EntityName { const { kind, namespace, name } = parseEntityRef(ref, { defaultNamespace: ENTITY_DEFAULT_NAMESPACE, @@ -149,7 +155,12 @@ export function parseEntityRef( */ export function parseEntityRef( ref: EntityRef, - context: EntityRefContext = {}, + context: { + /** The default kind, if none is given in the reference */ + defaultKind?: string; + /** The default namespace, if none is given in the reference */ + defaultNamespace?: string; + } = {}, ): { kind?: string; namespace?: string; @@ -184,54 +195,6 @@ export function parseEntityRef( }; } -/** - * Takes an entity reference or name, and outputs an entity reference on the - * most compact form possible. I.e. if the parts do not contain any - * special/reserved characters, it outputs the string form, otherwise it - * outputs the compound form. - * - * @public - * @deprecated Use `stringifyEntityRef` instead - * @param ref - The reference to serialize - * @returns The same reference on either string or compound form - */ -export function serializeEntityRef( - ref: - | Entity - | { - kind?: string; - namespace?: string; - name: string; - }, -): EntityRef { - let kind; - let namespace; - let name; - - if ('metadata' in ref) { - kind = ref.kind; - namespace = ref.metadata.namespace; - name = ref.metadata.name; - } else { - kind = ref.kind; - namespace = ref.namespace; - name = ref.name; - } - - if ( - kind?.includes(':') || - kind?.includes('/') || - namespace?.includes(':') || - namespace?.includes('/') || - name.includes(':') || - name.includes('/') - ) { - return { kind, namespace, name }; - } - - return `${kind ? `${kind}:` : ''}${namespace ? `${namespace}/` : ''}${name}`; -} - /** * Takes an entity or entity name/reference, and returns the string form of an * entity ref. @@ -282,11 +245,17 @@ export function stringifyEntityRef( * @param context - An optional context of default kind and namespace, that apply * to the ref if given * @returns True if matching, false otherwise + * @deprecated compare using stringifyEntityRef instead. */ export function compareEntityToRef( entity: Entity, ref: EntityRef | EntityName, - context?: EntityRefContext, + context?: { + /** The default kind, if none is given in the reference */ + defaultKind?: string; + /** The default namespace, if none is given in the reference */ + defaultNamespace?: string; + }, ): boolean { const entityKind = entity.kind; const entityNamespace = entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE; diff --git a/packages/catalog-model/src/entity/util.ts b/packages/catalog-model/src/entity/util.ts index 4506a8d852..78359b45f4 100644 --- a/packages/catalog-model/src/entity/util.ts +++ b/packages/catalog-model/src/entity/util.ts @@ -23,6 +23,7 @@ import { Entity, AlphaEntity } from './Entity'; * * @public * @returns A string with enough randomness to uniquely identify an entity + * @deprecated use `uuidv4()` instead. */ export function generateEntityUid(): string { return uuidv4(); @@ -34,6 +35,7 @@ export function generateEntityUid(): string { * @public * @returns A string with enough randomness to uniquely identify an entity * revision + * @deprecated will be removed in a future release. */ export function generateEntityEtag(): string { return Buffer.from(uuidv4(), 'utf8').toString('base64').replace(/[^\w]/g, ''); @@ -55,6 +57,7 @@ export function generateEntityEtag(): string { * @public * @param previous - The old state of the entity * @param next - The new state of the entity + * @deprecated will be removed in a future release. */ export function entityHasChanges(previous: Entity, next: Entity): boolean { const e1 = lodash.cloneDeep(previous); @@ -109,6 +112,7 @@ export function entityHasChanges(previous: Entity, next: Entity): boolean { * @param previous - The old state of the entity * @param next - The new state of the entity * @returns An entity with the merged state of both + * @deprecated will be removed in a future release. */ export function generateUpdatedEntity(previous: Entity, next: Entity): Entity { const { uid, etag, generation } = previous.metadata; diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts index be9f7a0d6a..7211c25a8d 100644 --- a/packages/catalog-model/src/kinds/index.ts +++ b/packages/catalog-model/src/kinds/index.ts @@ -50,8 +50,6 @@ export type { SystemEntityV1alpha1 as SystemEntity, SystemEntityV1alpha1, } from './SystemEntityV1alpha1'; -export { templateEntityV1beta2Validator } from './TemplateEntityV1beta2'; -export type { TemplateEntityV1beta2 } from './TemplateEntityV1beta2'; export type { KindValidator } from './types'; export { userEntityV1alpha1Validator } from './UserEntityV1alpha1'; export type { diff --git a/packages/catalog-model/src/location/annotation.ts b/packages/catalog-model/src/location/annotation.ts index 8eb393f555..3ff624360e 100644 --- a/packages/catalog-model/src/location/annotation.ts +++ b/packages/catalog-model/src/location/annotation.ts @@ -17,17 +17,41 @@ /** * Constant storing location annotation. * - * @public */ + * @public + * @deprecated use {@link ANNOTATION_LOCATION} instead. + * */ export const LOCATION_ANNOTATION = 'backstage.io/managed-by-location'; /** * Constant storing origin location annotation * - * @public */ + * @public + * @deprecated use {@link ANNOTATION_ORIGIN_LOCATION} instead. + */ export const ORIGIN_LOCATION_ANNOTATION = 'backstage.io/managed-by-origin-location'; /** * Contant storing source location annotation * - * @public */ + * @public + * @deprecated use {@link ANNOTATION_SOURCE_LOCATION} instead. + * */ export const SOURCE_LOCATION_ANNOTATION = 'backstage.io/source-location'; + +/** + * Constant storing location annotation. + * + * @public */ +export const ANNOTATION_LOCATION = 'backstage.io/managed-by-location'; +/** + * Constant storing origin location annotation + * + * @public */ +export const ANNOTATION_ORIGIN_LOCATION = + 'backstage.io/managed-by-origin-location'; + +/** + * Contant storing source location annotation + * + * @public */ +export const ANNOTATION_SOURCE_LOCATION = 'backstage.io/source-location'; diff --git a/packages/catalog-model/src/location/helpers.test.ts b/packages/catalog-model/src/location/helpers.test.ts index 020f7be1a1..91a2137611 100644 --- a/packages/catalog-model/src/location/helpers.test.ts +++ b/packages/catalog-model/src/location/helpers.test.ts @@ -16,47 +16,47 @@ import { getEntitySourceLocation, - parseLocationReference, - stringifyLocationReference, + parseLocationRef, + stringifyLocationRef, } from './helpers'; -describe('parseLocationReference', () => { +describe('parseLocationRef', () => { it('works for the simple case', () => { - expect(parseLocationReference('url:https://www.google.com')).toEqual({ + expect(parseLocationRef('url:https://www.google.com')).toEqual({ type: 'url', target: 'https://www.google.com', }); }); it('rejects faulty inputs', () => { - expect(() => parseLocationReference(7 as any)).toThrow( - "Unable to parse location reference '7', unexpected argument number", + expect(() => parseLocationRef(7 as any)).toThrow( + "Unable to parse location ref '7', unexpected argument number", ); - expect(() => parseLocationReference('')).toThrow( - "Unable to parse location reference '', expected ':', e.g. 'url:https://host/path'", + expect(() => parseLocationRef('')).toThrow( + "Unable to parse location ref '', expected ':', e.g. 'url:https://host/path'", ); - expect(() => parseLocationReference('hello')).toThrow( - "Unable to parse location reference 'hello', expected ':', e.g. 'url:https://host/path'", + expect(() => parseLocationRef('hello')).toThrow( + "Unable to parse location ref 'hello', expected ':', e.g. 'url:https://host/path'", ); - expect(() => parseLocationReference(':hello')).toThrow( - "Unable to parse location reference ':hello', expected ':', e.g. 'url:https://host/path'", + expect(() => parseLocationRef(':hello')).toThrow( + "Unable to parse location ref ':hello', expected ':', e.g. 'url:https://host/path'", ); - expect(() => parseLocationReference('hello:')).toThrow( - "Unable to parse location reference 'hello:', expected ':', e.g. 'url:https://host/path'", + expect(() => parseLocationRef('hello:')).toThrow( + "Unable to parse location ref 'hello:', expected ':', e.g. 'url:https://host/path'", ); - expect(() => parseLocationReference('http://blah')).toThrow( - "Invalid location reference 'http://blah', please prefix it with 'url:', e.g. 'url:http://blah'", + expect(() => parseLocationRef('http://blah')).toThrow( + "Invalid location ref 'http://blah', please prefix it with 'url:', e.g. 'url:http://blah'", ); - expect(() => parseLocationReference('https://bleh')).toThrow( - "Invalid location reference 'https://bleh', please prefix it with 'url:', e.g. 'url:https://bleh'", + expect(() => parseLocationRef('https://bleh')).toThrow( + "Invalid location ref 'https://bleh', please prefix it with 'url:', e.g. 'url:https://bleh'", ); }); }); -describe('stringifyLocationReference', () => { +describe('stringifyLocationRef', () => { it('works for the simple case', () => { expect( - stringifyLocationReference({ + stringifyLocationRef({ type: 'url', target: 'https://www.google.com', }), @@ -64,12 +64,12 @@ describe('stringifyLocationReference', () => { }); it('rejects faulty inputs', () => { - expect(() => - stringifyLocationReference({ type: '', target: 'hello' }), - ).toThrow('Unable to stringify location reference, empty type'); - expect(() => - stringifyLocationReference({ type: 'hello', target: '' }), - ).toThrow('Unable to stringify location reference, empty target'); + expect(() => stringifyLocationRef({ type: '', target: 'hello' })).toThrow( + 'Unable to stringify location ref, empty type', + ); + expect(() => stringifyLocationRef({ type: 'hello', target: '' })).toThrow( + 'Unable to stringify location ref, empty target', + ); }); }); diff --git a/packages/catalog-model/src/location/helpers.ts b/packages/catalog-model/src/location/helpers.ts index 1edd4e5ec5..d308c00449 100644 --- a/packages/catalog-model/src/location/helpers.ts +++ b/packages/catalog-model/src/location/helpers.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { ANNOTATION_SOURCE_LOCATION } from '.'; import { Entity, stringifyEntityRef } from '../entity'; -import { LOCATION_ANNOTATION, SOURCE_LOCATION_ANNOTATION } from './annotation'; +import { ANNOTATION_LOCATION } from './annotation'; /** * Parses a string form location reference. @@ -26,36 +27,53 @@ import { LOCATION_ANNOTATION, SOURCE_LOCATION_ANNOTATION } from './annotation'; * @public * @param ref - A string-form location reference, e.g. `'url:https://host'` * @returns A location reference, e.g. `{ type: 'url', target: 'https://host' }` + * @deprecated use {@link parseLocationRef} instead */ -export function parseLocationReference(ref: string): { +export function parseLocationReference(ref: string) { + return parseLocationRef(ref); +} + +/** + * Parses a string form location reference. + * + * @remarks + * + * Note that the return type is not `LocationSpec`, because we do not want to + * conflate the string form with the additional properties of that type. + * + * @public + * @param ref - A string-form location ref, e.g. `'url:https://host'` + * @returns A location ref, e.g. `{ type: 'url', target: 'https://host' }` + */ +export function parseLocationRef(ref: string): { type: string; target: string; } { if (typeof ref !== 'string') { throw new TypeError( - `Unable to parse location reference '${ref}', unexpected argument ${typeof ref}`, + `Unable to parse location ref '${ref}', unexpected argument ${typeof ref}`, ); } const splitIndex = ref.indexOf(':'); if (splitIndex < 0) { throw new TypeError( - `Unable to parse location reference '${ref}', expected ':', e.g. 'url:https://host/path'`, + `Unable to parse location ref '${ref}', expected ':', e.g. 'url:https://host/path'`, ); } - const type = ref.substr(0, splitIndex).trim(); - const target = ref.substr(splitIndex + 1).trim(); + const type = ref.substring(0, splitIndex).trim(); + const target = ref.substring(splitIndex + 1).trim(); if (!type || !target) { throw new TypeError( - `Unable to parse location reference '${ref}', expected ':', e.g. 'url:https://host/path'`, + `Unable to parse location ref '${ref}', expected ':', e.g. 'url:https://host/path'`, ); } if (type === 'http' || type === 'https') { throw new TypeError( - `Invalid location reference '${ref}', please prefix it with 'url:', e.g. 'url:${ref}'`, + `Invalid location ref '${ref}', please prefix it with 'url:', e.g. 'url:${ref}'`, ); } @@ -73,17 +91,37 @@ export function parseLocationReference(ref: string): { * @public * @param ref - A location reference, e.g. `{ type: 'url', target: 'https://host' }` * @returns A string-form location reference, e.g. `'url:https://host'` + * @deprecated use {@link stringifyLocationRef} instead */ export function stringifyLocationReference(ref: { type: string; target: string; +}): string { + return stringifyLocationRef(ref); +} + +/** + * Turns a location ref into its string form. + * + * @remarks + * + * Note that the input type is not `LocationSpec`, because we do not want to + * conflate the string form with the additional properties of that type. + * + * @public + * @param ref - A location ref, e.g. `{ type: 'url', target: 'https://host' }` + * @returns A string-form location ref, e.g. `'url:https://host'` + */ +export function stringifyLocationRef(ref: { + type: string; + target: string; }): string { const { type, target } = ref; if (!type) { - throw new TypeError(`Unable to stringify location reference, empty type`); + throw new TypeError(`Unable to stringify location ref, empty type`); } else if (!target) { - throw new TypeError(`Unable to stringify location reference, empty target`); + throw new TypeError(`Unable to stringify location ref, empty target`); } return `${type}:${target}`; @@ -105,8 +143,8 @@ export function getEntitySourceLocation(entity: Entity): { target: string; } { const locationRef = - entity.metadata?.annotations?.[SOURCE_LOCATION_ANNOTATION] ?? - entity.metadata?.annotations?.[LOCATION_ANNOTATION]; + entity.metadata?.annotations?.[ANNOTATION_SOURCE_LOCATION] ?? + entity.metadata?.annotations?.[ANNOTATION_LOCATION]; if (!locationRef) { throw new Error( @@ -114,5 +152,5 @@ export function getEntitySourceLocation(entity: Entity): { ); } - return parseLocationReference(locationRef); + return parseLocationRef(locationRef); } diff --git a/packages/catalog-model/src/location/index.ts b/packages/catalog-model/src/location/index.ts index ead4a6b564..8302ec202f 100644 --- a/packages/catalog-model/src/location/index.ts +++ b/packages/catalog-model/src/location/index.ts @@ -15,18 +15,18 @@ */ export { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, + ANNOTATION_SOURCE_LOCATION, LOCATION_ANNOTATION, ORIGIN_LOCATION_ANNOTATION, SOURCE_LOCATION_ANNOTATION, } from './annotation'; export { - parseLocationReference, - stringifyLocationReference, getEntitySourceLocation, + parseLocationRef, + parseLocationReference, + stringifyLocationRef, + stringifyLocationReference, } from './helpers'; export type { Location, LocationSpec } from './types'; -export { - analyzeLocationSchema, - locationSchema, - locationSpecSchema, -} from './validation'; diff --git a/packages/catalog-model/src/location/types.ts b/packages/catalog-model/src/location/types.ts index 725f873f2d..2ed8fd717b 100644 --- a/packages/catalog-model/src/location/types.ts +++ b/packages/catalog-model/src/location/types.ts @@ -35,6 +35,7 @@ export type LocationSpec = { * Entity location for a specific entity. * * @public + * @deprecated import from {@link @backstage/catalog-client#Location} instead. */ export type Location = { id: string; diff --git a/packages/catalog-model/src/location/validation.ts b/packages/catalog-model/src/location/validation.ts deleted file mode 100644 index 2fd692e649..0000000000 --- a/packages/catalog-model/src/location/validation.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 yup from 'yup'; -import { LocationSpec, Location } from './types'; - -/** - * Deprecated. - * - * @public - * @deprecated Use {@link JSONSchema} or validators instead. - */ -export const locationSpecSchema: yup.SchemaOf = yup - .object({ - type: yup.string().required(), - target: yup.string().required(), - presence: yup.mixed().oneOf(['required', 'optional']), - }) - .noUnknown() - .required(); - -/** - * Deprecated. - * - * @public - * @deprecated Use {@link JSONSchema} or validators instead. - */ -export const locationSchema: yup.SchemaOf = yup - .object({ - id: yup.string().required(), - type: yup.string().required(), - target: yup.string().required(), - presence: yup.mixed().oneOf(['required', 'optional']), - }) - .noUnknown() - .required(); - -/** - * Deprecated. - * - * @public - * @deprecated Use {@link JSONSchema} or validators instead. - */ -export const analyzeLocationSchema: yup.SchemaOf<{ location: LocationSpec }> = - yup - .object({ - location: locationSpecSchema, - }) - .noUnknown() - .required(); diff --git a/packages/catalog-model/src/types.ts b/packages/catalog-model/src/types.ts index 1a0fab267c..0526f8807e 100644 --- a/packages/catalog-model/src/types.ts +++ b/packages/catalog-model/src/types.ts @@ -21,6 +21,7 @@ import { JSONSchema7 } from 'json-schema'; * JSONSchema extendable by arbitrary JSON attributes * * @public + * @deprecated use JSONSchema7 from the json-schema package instead. */ export type JSONSchema = JSONSchema7 & { [key in string]?: JsonValue }; diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index e588c02edf..c890e44b29 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/cli-common +## 0.1.8 + +### Patch Changes + +- Fix for the previous release with missing type declarations. + +## 0.1.7 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` + ## 0.1.6 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index cdb4b01b6d..409c2e678e 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.6", + "version": "0.1.7", "private": false, "main": "src/index.ts", "types": "src/index.ts", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,12 +24,13 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "devDependencies": { "@types/jest": "^26.0.7", diff --git a/packages/cli/.snyk b/packages/cli/.snyk index 3ad43bd3de..0a32a6ac12 100644 --- a/packages/cli/.snyk +++ b/packages/cli/.snyk @@ -3,80 +3,65 @@ version: v1.22.1 # ignores vulnerabilities until expiry date; change duration by modifying expiry date ignore: SNYK-JS-ANSIHTML-1296849: - - 'webpack-dev-server > ansi-html': + - webpack-dev-server > ansi-html: reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-ANSIREGEX-1583908: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-CSSWHAT-1298035: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-BROWSERSLIST-1090194: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-ISSVG-1243891: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-ISSVG-1085627: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-POSTCSS-1255640: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-POSTCSS-1090595: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - SNYK-JS-WS-1296835: - '*': reason: Developer tools are not a valid target for ReDoS attacks expires: 2022-03-06T17:18:55.019Z created: 2021-09-06T17:18:55.027Z - - SNYK-JS-IMMER-1540542: - - '*': - reason: Prototype pollution is not an effective attack against a CLI as it already executes arbitrary code - expires: 2022-03-06T17:18:55.019Z - created: 2021-09-06T17:18:55.027Z - - SNYK-JS-SETVALUE-1540541: - - '*': - reason: Prototype pollution is not an effective attack against a CLI as it already executes arbitrary code - expires: 2022-03-06T17:18:55.019Z - created: 2021-09-06T17:18:55.027Z - 'snyk:lic:npm:rollup-plugin-dts:LGPL-3.0': - '*': - reason: Backstage itself does not redistribute this dependency in minified form + reason: This is a development dependency only and is therefore acceptable expires: 2031-09-06T17:18:55.027Z created: 2021-09-06T17:18:55.027Z - 'snyk:lic:npm:axe-core:MPL-2.0': - '*': - reason: Backstage itself does not redistribute this dependency in minified form + reason: This is a development dependency only and is therefore acceptable expires: 2031-09-06T17:18:55.027Z created: 2021-09-06T17:18:55.027Z + SNYK-JS-UNSETVALUE-2400660: + - '*': + reason: >- + The pollution in this vulnerability does not allow injection of + arbitrary values and is therefore a negligible risk for a CLI. + expires: 2022-08-17T21:54:43.658Z + created: 2022-02-15T21:54:43.668Z patch: {} diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 37bea1e016..c9eee943ad 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/cli +## 0.14.0 + +### Minor Changes + +- 1fc0cd3896: Bumped Webpack and Rollup `svgr` dependencies and updated the AST template for `.icon.svg` modules. This means that SVG icon imports are now using SVGO v2. + +### Patch Changes + +- 0b74c72987: Added a new experimental and hidden `backstage-cli repo lint` command that can be used to lint all packages in the project, similar to `lerna run lint`. +- 532dae9c4c: The `versions:bump --release next` command is updated to compare the `main` and `next` release manifests and prefer the latest. +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 22862486de: The `versions:bump` command now filters out `npm_` environment configuration when running `yarn install`. This has the effect of allowing it to consider local configuration files within the repository, which is the behavior that one would expect. +- 22862486de: The `versions:bump` command now also considers the root `package.json` when searching for updates. It has also received updates to its output, including a link the [Backstage upgrade helper](https://backstage.github.io/upgrade-helper) and silenced `yarn install` output. +- 7410e12268: Several changes were made to the new experimental package roles system. Unless you have been experimenting with using this new system, these changes have no affect on your project. + + Renamed the `backstage-cli migrate package-role` command to `backstage-cli migrate package-roles`. + + Updated the package role definitions by renaming `app` to `frontend`, `plugin-frontend` to `frontend-plugin`, `plugin-frontend-module` to `frontend-plugin-module`, `plugin-backend` to `backend-plugin`, and `plugin-backend-module` to `backend-plugin-module` + + The `backstage-cli migrate package-scripts` received several tweaks to make it more accurate. It now tries to maintain existing script arguments, like `--config` parameters for `build` and `start` scripts. + + The `script` command category has been renamed to `package`. + + The `backstage-cli package build` command set an incorrect target directory for `app` and `backend` packages, which has been fixed. + + The `backend:bundle` and `repo build` command for the `backend` role was previously ignoring building of bundled packages that had migrated to use package roles and the standard build script, this has now been fixed. + +- c6bbafb516: Updated the default [sucrase](https://github.com/alangpierce/sucrase)-based Jest transform to include source maps if the environment variable `ENABLE_SOURCE_MAPS` is non-empty. This can be used to better support editor test debugging integrations. +- 7410e12268: The `test` command now automatically adds `--passWithNoTests` to the Jest invocation. To revert this behavior, pass `--passWithNoTests=false` or `--no-passWithNoTests`. +- Updated dependencies + - @backstage/config-loader@0.9.4 + - @backstage/errors@0.2.1 + - @backstage/release-manifests@0.0.2 + - @backstage/cli-common@0.1.7 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.13.2 ### Patch Changes diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index 978c598584..d5b85b9748 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -102,9 +102,10 @@ async function getProjectConfig(targetPath, displayName) { }, transform: { - '\\.(js|jsx|ts|tsx|mjs|cjs)$': require.resolve( - './jestSucraseTransform.js', - ), + '\\.(js|jsx|ts|tsx|mjs|cjs)$': [ + require.resolve('./jestSucraseTransform.js'), + { enableSourceMaps: Boolean(process.env.ENABLE_SOURCE_MAPS) }, + ], '\\.(bmp|gif|jpg|jpeg|png|frag|xml|svg|eot|woff|woff2|ttf)$': require.resolve('./jestFileTransform.js'), '\\.(yaml)$': require.resolve('jest-transform-yaml'), @@ -174,7 +175,10 @@ async function getRootConfig() { // script to determine whether a given package should be tested const packageData = await fs.readJson(packagePath); const testScript = packageData.scripts && packageData.scripts.test; - if (testScript && testScript.includes('backstage-cli test')) { + const isSupportedTestScript = + testScript?.includes('backstage-cli test') || + testScript?.includes('backstage-cli package test'); + if (testScript && isSupportedTestScript) { return await getProjectConfig(projectPath, packageData.name); } diff --git a/packages/cli/config/jestSucraseTransform.js b/packages/cli/config/jestSucraseTransform.js index c88909d21f..d0400f4f3b 100644 --- a/packages/cli/config/jestSucraseTransform.js +++ b/packages/cli/config/jestSucraseTransform.js @@ -21,50 +21,71 @@ const sucrasePluginPkg = require('@sucrase/jest-plugin/package.json'); const ESM_REGEX = /\b(?:import|export)\b/; -function process(source, filePath) { - let transforms; +function createTransformer(config) { + const process = (source, filePath) => { + let transforms; - if (filePath.endsWith('.esm.js')) { - transforms = ['imports']; - } else if (filePath.endsWith('.js')) { - // This is a very rough filter to avoid transforming things that we quickly - // can be sure are definitely not ESM modules. - if (ESM_REGEX.test(source)) { - transforms = ['imports', 'jsx']; // JSX within .js is currently allowed + if (filePath.endsWith('.esm.js')) { + transforms = ['imports']; + } else if (filePath.endsWith('.js')) { + // This is a very rough filter to avoid transforming things that we quickly + // can be sure are definitely not ESM modules. + if (ESM_REGEX.test(source)) { + transforms = ['imports', 'jsx']; // JSX within .js is currently allowed + } + } else if (filePath.endsWith('.jsx')) { + transforms = ['jsx', 'imports']; + } else if (filePath.endsWith('.ts')) { + transforms = ['typescript', 'imports']; + } else if (filePath.endsWith('.tsx')) { + transforms = ['typescript', 'jsx', 'imports']; } - } else if (filePath.endsWith('.jsx')) { - transforms = ['jsx', 'imports']; - } else if (filePath.endsWith('.ts')) { - transforms = ['typescript', 'imports']; - } else if (filePath.endsWith('.tsx')) { - transforms = ['typescript', 'jsx', 'imports']; - } - // Only apply the jest transform to the test files themselves - if (transforms && filePath.includes('.test.')) { - transforms.push('jest'); - } + // Only apply the jest transform to the test files themselves + if (transforms && filePath.includes('.test.')) { + transforms.push('jest'); + } - if (transforms) { - return transform(source, { - transforms, - filePath, - disableESTransforms: true, - }).code; - } + if (transforms) { + const { code, sourceMap: map } = transform(source, { + transforms, + filePath, + disableESTransforms: true, + sourceMapOptions: { + compiledFilename: filePath, + }, + }); + if (config.enableSourceMaps) { + const b64 = Buffer.from(JSON.stringify(map), 'utf8').toString('base64'); + const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${b64}`; + // Include both inline and object source maps, as inline source maps are + // needed for support of some editor integrations. + return { code: `${code}\n${suffix}`, map }; + } + // We only return the `map` result if source maps are enabled, as they + // have a negative impact on the coverage accuracy. + return code; + } - return source; + return source; + }; + + // TODO: contribute something like this to @sucrase/jest-plugin + const getCacheKey = sourceText => { + return createHash('md5') + .update(sourceText) + .update(Buffer.alloc(1)) + .update(sucrasePkg.version) + .update(Buffer.alloc(1)) + .update(sucrasePluginPkg.version) + .update(Buffer.alloc(1)) + .update(JSON.stringify(config)) + .update(Buffer.alloc(1)) + .update('1') // increment whenever the transform logic in this file changes + .digest('hex'); + }; + + return { process, getCacheKey }; } -// TODO: contribute something like this to @sucrase/jest-plugin -function getCacheKey(sourceText) { - return createHash('md5') - .update(sourceText) - .update(Buffer.alloc(1)) - .update(sucrasePkg.version) - .update(Buffer.alloc(1)) - .update(sucrasePluginPkg.version) - .digest('hex'); -} - -module.exports = { process, getCacheKey }; +module.exports = { createTransformer }; diff --git a/packages/cli/package.json b/packages/cli/package.json index 589ac58646..8531bf0750 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,11 +1,14 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.13.2", + "version": "0.14.0", "private": false, "publishConfig": { "access": "public" }, + "backstage": { + "role": "cli" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -18,23 +21,23 @@ "license": "Apache-2.0", "main": "dist/index.cjs.js", "scripts": { - "build": "backstage-cli build --outputs cjs", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "clean": "backstage-cli clean", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", "start": "nodemon --" }, "bin": { "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.6", - "@backstage/config": "^0.1.13", - "@backstage/config-loader": "^0.9.3", - "@backstage/errors": "^0.2.0", - "@backstage/release-manifests": "^0.0.1", - "@backstage/types": "^0.1.1", - "@hot-loader/react-dom": "^16.13.0", + "@backstage/cli-common": "^0.1.7", + "@backstage/config": "^0.1.14", + "@backstage/config-loader": "^0.9.4", + "@backstage/errors": "^0.2.1", + "@backstage/release-manifests": "^0.0.2", + "@backstage/types": "^0.1.2", + "@hot-loader/react-dom": "^17.0.2", "@manypkg/get-packages": "^1.1.3", "@octokit/request": "^5.4.12", "@rollup/plugin-commonjs": "^21.0.1", @@ -48,8 +51,8 @@ "@sucrase/webpack-loader": "^2.0.0", "@svgr/plugin-jsx": "6.2.x", "@svgr/plugin-svgo": "6.2.x", - "@svgr/rollup": "5.5.x", - "@svgr/webpack": "5.5.x", + "@svgr/rollup": "6.2.x", + "@svgr/webpack": "6.2.x", "@types/webpack-env": "^1.15.2", "@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/parser": "^5.9.0", @@ -118,14 +121,14 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", - "@backstage/theme": "^0.2.14", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", + "@backstage/theme": "^0.2.15", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", @@ -137,7 +140,8 @@ "@types/npm-packlist": "^1.1.2", "@types/recursive-readdir": "^2.2.0", "@types/rollup-plugin-peer-deps-external": "^2.2.0", - "@types/rollup-plugin-postcss": "^2.0.0", + "@types/rollup-plugin-postcss": "^3.1.4", + "@types/svgo": "^2.6.2", "@types/tar": "^6.1.1", "@types/terser-webpack-plugin": "^5.0.4", "@types/yarnpkg__lockfile": "^1.1.4", diff --git a/packages/cli/src/commands/build/buildBackend.ts b/packages/cli/src/commands/build/buildBackend.ts index e32b7956db..0768728f00 100644 --- a/packages/cli/src/commands/build/buildBackend.ts +++ b/packages/cli/src/commands/build/buildBackend.ts @@ -49,19 +49,20 @@ export async function buildBackend(options: BuildBackendOptions) { // We built the target backend package using the regular build process, but the result of // that has now been packed into the dist workspace, so clean up the dist dir. - await fs.remove(targetDir); - await fs.mkdir(targetDir); + const distDir = resolvePath(targetDir, 'dist'); + await fs.remove(distDir); + await fs.mkdir(distDir); // Move out skeleton.tar.gz before we create the main bundle, no point having that included up twice. await fs.move( resolvePath(tmpDir, SKELETON_FILE), - resolvePath(targetDir, SKELETON_FILE), + resolvePath(distDir, SKELETON_FILE), ); // Create main bundle.tar.gz, with some tweaks to make it more likely hit Docker build cache. await tar.create( { - file: resolvePath(targetDir, BUNDLE_FILE), + file: resolvePath(distDir, BUNDLE_FILE), cwd: tmpDir, portable: true, noMtime: true, diff --git a/packages/cli/src/commands/build/buildApp.ts b/packages/cli/src/commands/build/buildFrontend.ts similarity index 95% rename from packages/cli/src/commands/build/buildApp.ts rename to packages/cli/src/commands/build/buildFrontend.ts index b0959b2d6a..6d7ca2e6a9 100644 --- a/packages/cli/src/commands/build/buildApp.ts +++ b/packages/cli/src/commands/build/buildFrontend.ts @@ -26,7 +26,7 @@ interface BuildAppOptions { configPaths: string[]; } -export async function buildApp(options: BuildAppOptions) { +export async function buildFrontend(options: BuildAppOptions) { const { targetDir, writeStats, configPaths } = options; const { name } = await fs.readJson(resolvePath(targetDir, 'package.json')); await buildBundle({ diff --git a/packages/cli/src/commands/build/command.ts b/packages/cli/src/commands/build/command.ts index 1189883b12..5c8065dbb4 100644 --- a/packages/cli/src/commands/build/command.ts +++ b/packages/cli/src/commands/build/command.ts @@ -18,22 +18,22 @@ import { Command } from 'commander'; import { buildPackage, Output } from '../../lib/builder'; import { findRoleFromCommand, getRoleInfo } from '../../lib/role'; import { paths } from '../../lib/paths'; -import { buildApp } from './buildApp'; +import { buildFrontend } from './buildFrontend'; import { buildBackend } from './buildBackend'; export async function command(cmd: Command): Promise { const role = await findRoleFromCommand(cmd); - if (role === 'app') { - return buildApp({ - targetDir: paths.resolveTarget('dist'), + if (role === 'frontend') { + return buildFrontend({ + targetDir: paths.targetDir, configPaths: cmd.config as string[], writeStats: Boolean(cmd.stats), }); } if (role === 'backend') { return buildBackend({ - targetDir: paths.resolveTarget('dist'), + targetDir: paths.targetDir, skipBuildDependencies: Boolean(cmd.skipBuildDependencies), }); } diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 770d216ba2..d3baa37b3f 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -42,18 +42,36 @@ export function registerRepoCommand(program: CommanderStatic) { 'Build all packages, including bundled app and backend packages.', ) .action(lazy(() => import('./repo/build').then(m => m.command))); + + command + .command('lint') + .description('Lint all packages in the project') + .option( + '--format ', + 'Lint report output format', + 'eslint-formatter-friendly', + ) + .option( + '--since ', + 'Only lint packages that changed since the specified ref', + ) + .option('--fix', 'Attempt to automatically fix violations') + .action(lazy(() => import('./repo/lint').then(m => m.command))); } export function registerScriptCommand(program: CommanderStatic) { const command = program - .command('script [command]', { hidden: true }) - .description('Lifecycle scripts for Backstage packages [EXPERIMENTAL]'); + .command('package [command]', { hidden: true }) + .description('Lifecycle scripts for individual packages [EXPERIMENTAL]'); command .command('start') .description('Start a package for local development') .option(...configOption) - .option('--role ', 'Run the command with an explicit package role') + .option( + '--role ', + 'Run the command with an explicit package role [EXPERIMENTAL]', + ) .option('--check', 'Enable type checking and linting if available') .option('--inspect', 'Enable debugger in Node.js environments') .option( @@ -65,6 +83,10 @@ export function registerScriptCommand(program: CommanderStatic) { command .command('build') .description('Build a package for production deployment or publishing') + .option( + '--role ', + 'Run the command with an explicit package role [EXPERIMENTAL]', + ) .option( '--minify', 'Minify the generated code. Does not apply to app or backend packages.', @@ -89,7 +111,7 @@ export function registerScriptCommand(program: CommanderStatic) { ) .action(lazy(() => import('./build').then(m => m.command))); - program + command .command('lint') .option( '--format ', @@ -100,7 +122,7 @@ export function registerScriptCommand(program: CommanderStatic) { .description('Lint a package') .action(lazy(() => import('./lint').then(m => m.default))); - program + command .command('test') .allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args .helpOption(', --backstage-cli-help') // Let Jest handle help @@ -129,7 +151,7 @@ export function registerMigrateCommand(program: CommanderStatic) { .description('Migration utilities [EXPERIMENTAL]'); command - .command('package-role') + .command('package-roles') .description(`Add package role field to packages that don't have it`) .action(lazy(() => import('./migrate/packageRole').then(m => m.default))); @@ -142,7 +164,7 @@ export function registerMigrateCommand(program: CommanderStatic) { } export function registerCommands(program: CommanderStatic) { - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('app:build') .description('Build an app for a production release') @@ -150,7 +172,7 @@ export function registerCommands(program: CommanderStatic) { .option(...configOption) .action(lazy(() => import('./app/build').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('app:serve') .description('Serve an app for local development') @@ -158,7 +180,7 @@ export function registerCommands(program: CommanderStatic) { .option(...configOption) .action(lazy(() => import('./app/serve').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('backend:build') .description('Build a backend plugin') @@ -166,7 +188,7 @@ export function registerCommands(program: CommanderStatic) { .option('--experimental-type-build', 'Enable experimental type build') .action(lazy(() => import('./backend/build').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('backend:bundle') .description('Bundle the backend into a deployment archive') @@ -176,7 +198,7 @@ export function registerCommands(program: CommanderStatic) { ) .action(lazy(() => import('./backend/bundle').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('backend:dev') .description('Start local development server with HMR for the backend') @@ -225,7 +247,7 @@ export function registerCommands(program: CommanderStatic) { lazy(() => import('./create-plugin/createPlugin').then(m => m.default)), ); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('plugin:build') .description('Build a plugin') @@ -233,7 +255,7 @@ export function registerCommands(program: CommanderStatic) { .option('--experimental-type-build', 'Enable experimental type build') .action(lazy(() => import('./plugin/build').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('plugin:serve') .description('Serves the dev/ folder of a plugin') @@ -248,7 +270,7 @@ export function registerCommands(program: CommanderStatic) { .description('Diff an existing plugin with the creation template') .action(lazy(() => import('./plugin/diff').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('build') .description('Build a package for publishing') @@ -257,7 +279,7 @@ export function registerCommands(program: CommanderStatic) { .option('--experimental-type-build', 'Enable experimental type build') .action(lazy(() => import('./oldBuild').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('lint') .option( @@ -269,7 +291,7 @@ export function registerCommands(program: CommanderStatic) { .description('Lint a package') .action(lazy(() => import('./lint').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('test') .allowUnknownOption(true) // Allows the command to run, but we still need to parse raw args @@ -355,19 +377,19 @@ export function registerCommands(program: CommanderStatic) { .description('Check Backstage package versioning') .action(lazy(() => import('./versions/lint').then(m => m.default))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('prepack') .description('Prepares a package for packaging before publishing') .action(lazy(() => import('./pack').then(m => m.pre))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('postpack') .description('Restores the changes made by the prepack command') .action(lazy(() => import('./pack').then(m => m.post))); - // TODO(Rugvip): Deprecate in favor of script variant + // TODO(Rugvip): Deprecate in favor of package variant program .command('clean') .description('Delete cache directories') diff --git a/packages/cli/src/commands/migrate/packageScripts.ts b/packages/cli/src/commands/migrate/packageScripts.ts index a3fdd20018..c7dab9466b 100644 --- a/packages/cli/src/commands/migrate/packageScripts.ts +++ b/packages/cli/src/commands/migrate/packageScripts.ts @@ -19,6 +19,8 @@ import { resolve as resolvePath } from 'path'; import { PackageGraph } from '../../lib/monorepo'; import { getRoleFromPackage, getRoleInfo, PackageRole } from '../../lib/role'; +const configArgPattern = /--config[=\s][^\s$]+/; + const noStartRoles: PackageRole[] = ['cli', 'common-library']; export async function command() { @@ -33,17 +35,52 @@ export async function command() { const roleInfo = getRoleInfo(role); const hasStart = !noStartRoles.includes(role); - const isBundled = roleInfo.output.includes('bundle'); + const needsPack = !(roleInfo.output.includes('bundle') || role === 'cli'); + const scripts = packageJson.scripts ?? {}; + + const startCmd = ['start']; + if (scripts.start?.includes('--check')) { + startCmd.push('--check'); + } + if (scripts.start?.includes('--config')) { + startCmd.push(...(scripts.start.match(configArgPattern) ?? [])); + } + + const buildCmd = ['build']; + if (scripts.build?.includes('--minify')) { + buildCmd.push('--minify'); + } + if (scripts.build?.includes('--experimental-type-build')) { + buildCmd.push('--experimental-type-build'); + } + if (scripts.build?.includes('--config')) { + buildCmd.push(...(scripts.build.match(configArgPattern) ?? [])); + } + + // For test scripts we keep all existing flags except for --passWithNoTests, since that's now default + const testCmd = ['test']; + if (scripts.test?.startsWith('backstage-cli test')) { + const args = scripts.test + .slice('backstage-cli test'.length) + .split(' ') + .filter(Boolean); + if (args.includes('--passWithNoTests')) { + args.splice(args.indexOf('--passWithNoTests'), 1); + } + testCmd.push(...args); + } const expectedScripts = { - ...(hasStart && { start: 'backstage-cli script start' }), - build: 'backstage-cli script build', - lint: 'backstage-cli script lint', - test: 'backstage-cli script test', - clean: 'backstage-cli script clean', - ...(!isBundled && { - postpack: 'backstage-cli script postpack', - prepack: 'backstage-cli script prepack', + ...(hasStart && { + start: `backstage-cli package ${startCmd.join(' ')}`, + }), + build: `backstage-cli package ${buildCmd.join(' ')}`, + lint: 'backstage-cli package lint', + test: `backstage-cli package ${testCmd.join(' ')}`, + clean: 'backstage-cli package clean', + ...(needsPack && { + postpack: 'backstage-cli package postpack', + prepack: 'backstage-cli package prepack', }), }; @@ -52,7 +89,12 @@ export async function command() { (packageJson.scripts = packageJson.scripts || {}); for (const [name, value] of Object.entries(expectedScripts)) { - if (currentScripts[name] !== value) { + const currentScript = currentScripts[name]; + + const isMissing = !currentScript; + const isDifferent = currentScript !== value; + const isBackstageScript = currentScript?.includes('backstage-cli'); + if (isMissing || (isDifferent && isBackstageScript)) { changed = true; currentScripts[name] = value; } diff --git a/packages/cli/src/commands/repo/build.ts b/packages/cli/src/commands/repo/build.ts index 9c32386304..ceb468ebfa 100644 --- a/packages/cli/src/commands/repo/build.ts +++ b/packages/cli/src/commands/repo/build.ts @@ -23,7 +23,7 @@ import { ExtendedPackage } from '../../lib/monorepo/PackageGraph'; import { runParallelWorkers } from '../../lib/parallel'; import { paths } from '../../lib/paths'; import { detectRoleFromPackage } from '../../lib/role'; -import { buildApp } from '../build/buildApp'; +import { buildFrontend } from '../build/buildFrontend'; import { buildBackend } from '../build/buildBackend'; function createScriptOptionsParser(anyCmd: Command, commandPath: string[]) { @@ -43,7 +43,9 @@ function createScriptOptionsParser(anyCmd: Command, commandPath: string[]) { } if (!targetCmd) { - throw new Error(`Could not find script command '${commandPath.join(' ')}'`); + throw new Error( + `Could not find package command '${commandPath.join(' ')}'`, + ); } const cmd = targetCmd; @@ -80,7 +82,7 @@ export async function command(cmd: Command): Promise { const apps = new Array(); const backends = new Array(); - const parseBuildScript = createScriptOptionsParser(cmd, ['script', 'build']); + const parseBuildScript = createScriptOptionsParser(cmd, ['package', 'build']); const options = packages.flatMap(pkg => { const role = @@ -90,7 +92,7 @@ export async function command(cmd: Command): Promise { return []; } - if (role === 'app') { + if (role === 'frontend') { apps.push(pkg); return []; } else if (role === 'backend') { @@ -137,7 +139,7 @@ export async function command(cmd: Command): Promise { ); return; } - await buildApp({ + await buildFrontend({ targetDir: pkg.dir, configPaths: (buildOptions.config as string[]) ?? [], writeStats: Boolean(buildOptions.stats), diff --git a/packages/cli/src/commands/repo/lint.ts b/packages/cli/src/commands/repo/lint.ts new file mode 100644 index 0000000000..b054dabe34 --- /dev/null +++ b/packages/cli/src/commands/repo/lint.ts @@ -0,0 +1,113 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 chalk from 'chalk'; +import { Command } from 'commander'; +import { relative as relativePath } from 'path'; +import { PackageGraph, ExtendedPackageJSON } from '../../lib/monorepo'; +import { runWorkerQueueThreads } from '../../lib/parallel'; +import { paths } from '../../lib/paths'; + +function depCount(pkg: ExtendedPackageJSON) { + const deps = pkg.dependencies ? Object.keys(pkg.dependencies).length : 0; + const devDeps = pkg.devDependencies + ? Object.keys(pkg.devDependencies).length + : 0; + return deps + devDeps; +} + +export async function command(cmd: Command): Promise { + let packages = await PackageGraph.listTargetPackages(); + + if (cmd.since) { + const graph = PackageGraph.fromPackages(packages); + packages = await graph.listChangedPackages({ ref: cmd.since }); + } + + // Packages are ordered from most to least number of dependencies, as a + // very cheap way of guessing which packages are more likely to be larger. + packages.sort((a, b) => depCount(b.packageJson) - depCount(a.packageJson)); + + // This formatter uses the cwd to format file paths, so let's have that happen from the root instead + if (cmd.format === 'eslint-formatter-friendly') { + process.chdir(paths.targetRoot); + } + + // Make sure lint output is colored unless the user explicitly disabled it + if (!process.env.FORCE_COLOR) { + process.env.FORCE_COLOR = '1'; + } + + const resultsList = await runWorkerQueueThreads({ + items: packages.map(pkg => ({ + fullDir: pkg.dir, + relativeDir: relativePath(paths.targetRoot, pkg.dir), + })), + workerData: { + fix: Boolean(cmd.fix), + format: cmd.format as string | undefined, + }, + workerFactory: async ({ fix, format }) => { + const { ESLint } = require('eslint'); + + return async ({ + fullDir, + relativeDir, + }): Promise<{ relativeDir: string; resultText: string }> => { + // Bit of a hack to make file resolutions happen from the correct directory + // since some lint rules don't respect the cwd of ESLint + process.cwd = () => fullDir; + + const start = Date.now(); + const eslint = new ESLint({ + cwd: fullDir, + fix, + extensions: ['js', 'jsx', 'ts', 'tsx', 'mjs', 'cjs'], + }); + const formatter = await eslint.loadFormatter(format); + + const results = await eslint.lintFiles(['.']); + + const count = String(results.length).padStart(3); + const time = ((Date.now() - start) / 1000).toFixed(2); + console.log(`Checked ${count} files in ${relativeDir} ${time}s`); + + if (fix) { + await ESLint.outputFixes(results); + } + + const resultText = formatter.format(results); + + return { relativeDir, resultText }; + }; + }, + }); + + let failed = false; + for (const { relativeDir, resultText } of resultsList) { + if (resultText) { + console.log(); + console.log(chalk.red(`Lint failed in ${relativeDir}:`)); + console.log(resultText.trimLeft()); + + failed = true; + } + } + + if (failed) { + process.exit(1); + } +} diff --git a/packages/cli/src/commands/start/command.ts b/packages/cli/src/commands/start/command.ts index 6615d5fd46..7a11028800 100644 --- a/packages/cli/src/commands/start/command.ts +++ b/packages/cli/src/commands/start/command.ts @@ -31,19 +31,19 @@ export async function command(cmd: Command): Promise { switch (role) { case 'backend': - case 'plugin-backend': - case 'plugin-backend-module': + case 'backend-plugin': + case 'backend-plugin-module': case 'node-library': return startBackend(options); - case 'app': + case 'frontend': return startFrontend({ ...options, entry: 'src/index', verifyVersions: true, }); case 'web-library': - case 'plugin-frontend': - case 'plugin-frontend-module': + case 'frontend-plugin': + case 'frontend-plugin-module': return startFrontend({ entry: 'dev/index', ...options }); default: throw new Error( diff --git a/packages/cli/src/commands/testCommand.ts b/packages/cli/src/commands/testCommand.ts index 24a4e06f9e..7165b20925 100644 --- a/packages/cli/src/commands/testCommand.ts +++ b/packages/cli/src/commands/testCommand.ts @@ -29,7 +29,11 @@ function includesAnyOf(hayStack: string[], ...needles: string[]) { export default async (cmd: Command) => { // all args are forwarded to jest - const rawArgs = cmd.parent.rawArgs as string[]; + let parent = cmd; + while (parent.parent) { + parent = parent.parent; + } + const rawArgs = parent.rawArgs as string[]; const args = rawArgs.slice(rawArgs.indexOf('test') + 1); // Only include our config if caller isn't passing their own config @@ -37,6 +41,10 @@ export default async (cmd: Command) => { args.push('--config', paths.resolveOwn('config/jest.js')); } + if (!includesAnyOf(args, '--no-passWithNoTests', '--passWithNoTests=false')) { + args.push('--passWithNoTests'); + } + // Run in watch mode unless in CI, coverage mode, or running all tests if ( !process.env.CI && diff --git a/packages/cli/src/commands/versions/bump.test.ts b/packages/cli/src/commands/versions/bump.test.ts index d2d3cf1573..e7b3c858aa 100644 --- a/packages/cli/src/commands/versions/bump.test.ts +++ b/packages/cli/src/commands/versions/bump.test.ts @@ -31,6 +31,7 @@ import { rest } from 'msw'; // Remove log coloring to simplify log matching jest.mock('chalk', () => ({ + red: (str: string) => str, blue: (str: string) => str, cyan: (str: string) => str, green: (str: string) => str, @@ -38,6 +39,18 @@ jest.mock('chalk', () => ({ yellow: (str: string) => str, })); +jest.mock('ora', () => ({ + __esModule: true, + default({ prefixText }: any) { + console.log(prefixText); + return { + start: () => ({ + succeed: () => {}, + }), + }; + }, +})); + const REGISTRY_VERSIONS: { [name: string]: string } = { '@backstage/core': '1.0.6', '@backstage/core-api': '1.0.7', @@ -177,7 +190,11 @@ describe('bump', () => { ); expect(runObj.run).toHaveBeenCalledTimes(1); - expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); expect(lockfileContents).toBe(lockfileMockResult); @@ -273,7 +290,7 @@ describe('bump', () => { 'unlocking @backstage/core-api@^1.0.6 ~> 1.0.7', 'unlocking @backstage/core-api@^1.0.3 ~> 1.0.7', 'bumping @backstage/theme in b to ^5.0.0', - 'Creating backstage.json', + 'Your project is now at version 0.0.1, which has been written to backstage.json', 'Running yarn install to install new versions', '⚠️ The following packages may have breaking changes:', ' @backstage/theme : 1.0.0 ~> 5.0.0', @@ -296,7 +313,11 @@ describe('bump', () => { ); expect(runObj.run).toHaveBeenCalledTimes(1); - expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); expect(lockfileContents).toBe(lockfileMockResult); @@ -389,7 +410,7 @@ describe('bump', () => { 'Some packages are outdated, updating', 'bumping @backstage/core in a to ^5.0.0', 'bumping @backstage/core in b to ^5.0.0', - 'Creating backstage.json', + 'Your project is now at version 2.0.0, which has been written to backstage.json', 'Running yarn install to install new versions', '⚠️ The following packages may have breaking changes:', ' @backstage/core : 1.0.3 ~> 5.0.0', @@ -398,7 +419,11 @@ describe('bump', () => { ]); expect(runObj.run).toHaveBeenCalledTimes(1); - expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); const packageA = await fs.readJson('/packages/a/package.json'); expect(packageA).toEqual({ @@ -418,6 +443,109 @@ describe('bump', () => { expect(await fs.readJson('/backstage.json')).toEqual({ version: '2.0.0' }); }); + it('should prefer versions from the highest manifest version when main is not specified', async () => { + mockFs({ + '/yarn.lock': lockfileMock, + '/package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + '/packages/a/package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), + '/packages/b/package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), + }); + + jest + .spyOn(paths, 'resolveTargetRoot') + .mockImplementation((...path) => resolvePath('/', ...path)); + jest.spyOn(runObj, 'runPlain').mockImplementation(async (...[, , , name]) => + JSON.stringify({ + type: 'inspect', + data: { + name: name, + 'dist-tags': { + latest: REGISTRY_VERSIONS[name], + }, + }, + }), + ); + jest.spyOn(runObj, 'run').mockResolvedValue(undefined); + worker.use( + rest.get( + 'https://versions.backstage.io/v1/tags/main/manifest.json', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + releaseVersion: '1.0.0', + packages: [ + { + name: '@backstage/theme', + version: '5.0.0', + }, + { + name: '@backstage/create-app', + version: '3.0.0', + }, + ], + }), + ), + ), + rest.get( + 'https://versions.backstage.io/v1/tags/next/manifest.json', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + releaseVersion: '1.0.0-next.1', + packages: [ + { + name: '@backstage/theme', + version: '4.0.0', + }, + { + name: '@backstage/create-app', + version: '2.0.0', + }, + ], + }), + ), + ), + ); + const { log: logs } = await withLogCollector(['log'], async () => { + await bump({ pattern: null, release: 'next' } as unknown as Command); + }); + expect(logs.filter(Boolean)).toEqual([ + 'Using default pattern glob @backstage/*', + 'Checking for updates of @backstage/core', + 'Checking for updates of @backstage/theme', + 'Checking for updates of @backstage/theme', + 'Checking for updates of @backstage/core-api', + 'Some packages are outdated, updating', + 'unlocking @backstage/core@^1.0.3 ~> 1.0.6', + 'unlocking @backstage/core-api@^1.0.6 ~> 1.0.7', + 'unlocking @backstage/core-api@^1.0.3 ~> 1.0.7', + 'bumping @backstage/theme in b to ^5.0.0', + 'Your project is now at version 1.0.0, which has been written to backstage.json', + 'Running yarn install to install new versions', + '⚠️ The following packages may have breaking changes:', + ' @backstage/theme : 1.0.0 ~> 5.0.0', + ' https://github.com/backstage/backstage/blob/master/packages/theme/CHANGELOG.md', + 'Version bump complete!', + ]); + }); + it('should bump backstage dependencies and dependencies matching pattern glob', async () => { const customLockfileMock = `${lockfileMock} "@backstage-extra/custom@^1.1.0": @@ -542,7 +670,11 @@ describe('bump', () => { ); expect(runObj.run).toHaveBeenCalledTimes(1); - expect(runObj.run).toHaveBeenCalledWith('yarn', ['install']); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); expect(lockfileContents).toEqual(customLockfileMockResult); @@ -662,8 +794,16 @@ describe('bumpBackstageJsonVersion', () => { .spyOn(paths, 'resolveTargetRoot') .mockImplementation((...path) => resolvePath('/', ...path)); - await bumpBackstageJsonVersion('1.4.1'); + const { log } = await withLogCollector(async () => { + await bumpBackstageJsonVersion('1.4.1'); + }); expect(await fs.readJson('/backstage.json')).toEqual({ version: '1.4.1' }); + expect(log).toEqual([ + 'Upgraded from release 0.0.1 to 1.4.1, please review these template changes:', + undefined, + ' https://backstage.github.io/upgrade-helper/?from=0.0.1&to=1.4.1', + undefined, + ]); }); it("should create backstage.json if doesn't exist", async () => { @@ -674,8 +814,13 @@ describe('bumpBackstageJsonVersion', () => { .spyOn(paths, 'resolveTargetRoot') .mockImplementation((...path) => resolvePath('/', ...path)); - await bumpBackstageJsonVersion(latest); + const { log } = await withLogCollector(async () => { + await bumpBackstageJsonVersion(latest); + }); expect(await fs.readJson('/backstage.json')).toEqual({ version: latest }); + expect(log).toEqual([ + 'Your project is now at version 1.4.1, which has been written to backstage.json', + ]); }); }); diff --git a/packages/cli/src/commands/versions/bump.ts b/packages/cli/src/commands/versions/bump.ts index fc455b9fbd..b9d318bccc 100644 --- a/packages/cli/src/commands/versions/bump.ts +++ b/packages/cli/src/commands/versions/bump.ts @@ -16,6 +16,7 @@ import fs from 'fs-extra'; import chalk from 'chalk'; +import ora from 'ora'; import semver from 'semver'; import minimatch from 'minimatch'; import { Command } from 'commander'; @@ -68,15 +69,30 @@ export default async (cmd: Command) => { let findTargetVersion: (name: string) => Promise; let releaseManifest: ReleaseManifest; + // Specific release specified. Be strict when resolving versions if (semver.valid(cmd.release)) { releaseManifest = await getManifestByVersion({ version: cmd.release }); findTargetVersion = createStrictVersionFinder({ releaseManifest, }); } else { - releaseManifest = await getManifestByReleaseLine({ - releaseLine: cmd.release, - }); + // Release line specified. Be lenient when resolving versions. + if (cmd.release === 'next') { + const next = await getManifestByReleaseLine({ + releaseLine: 'next', + }); + const main = await getManifestByReleaseLine({ + releaseLine: 'main', + }); + // Prefer manifest with the latest release version + releaseManifest = semver.gt(next.releaseVersion, main.releaseVersion) + ? next + : main; + } else { + releaseManifest = await getManifestByReleaseLine({ + releaseLine: cmd.release, + }); + } findTargetVersion = createVersionFinder({ releaseLine: cmd.releaseLine, releaseManifest, @@ -244,12 +260,8 @@ export default async (cmd: Command) => { ), ); } - console.log(); - console.log( - `Running ${chalk.blue('yarn install')} to install new versions`, - ); - console.log(); - await run('yarn', ['install']); + + await runYarnInstall(); if (breakingUpdates.size > 0) { console.log(); @@ -405,17 +417,34 @@ export async function bumpBackstageJsonVersion(version: string) { throw e; }); - if (backstageJson?.version === version) { + const prevVersion = backstageJson?.version; + + if (prevVersion === version) { return; } - console.log( - chalk.yellow( - typeof backstageJson === 'undefined' - ? `Creating ${BACKSTAGE_JSON}` - : `Bumping version in ${BACKSTAGE_JSON}`, - ), - ); + const { yellow, cyan, green } = chalk; + if (prevVersion) { + const from = encodeURIComponent(prevVersion); + const to = encodeURIComponent(version); + const link = `https://backstage.github.io/upgrade-helper/?from=${from}&to=${to}`; + console.log( + yellow( + `Upgraded from release ${green(prevVersion)} to ${green( + version, + )}, please review these template changes:`, + ), + ); + console.log(); + console.log(` ${cyan(link)}`); + console.log(); + } else { + console.log( + yellow( + `Your project is now at version ${version}, which has been written to ${BACKSTAGE_JSON}`, + ), + ); + } await fs.writeJson( backstageJsonPath, @@ -426,3 +455,35 @@ export async function bumpBackstageJsonVersion(version: string) { }, ); } + +async function runYarnInstall() { + const spinner = ora({ + prefixText: `Running ${chalk.blue('yarn install')} to install new versions`, + spinner: 'arc', + color: 'green', + }).start(); + + const installOutput = new Array(); + try { + await run('yarn', ['install'], { + env: { + FORCE_COLOR: 'true', + // We filter out all of the npm_* environment variables that are added when + // executing through yarn. This works around an issue where these variables + // incorrectly override local yarn or npm config in the project directory. + ...Object.fromEntries( + Object.entries(process.env).map(([name, value]) => + name.startsWith('npm_') ? [name, undefined] : [name, value], + ), + ), + }, + stdoutLogFunc: data => installOutput.push(data), + stderrLogFunc: data => installOutput.push(data), + }); + spinner.succeed(); + } catch (error) { + spinner.fail(); + process.stdout.write(Buffer.concat(installOutput)); + throw error; + } +} diff --git a/packages/cli/src/lib/builder/buildTypeDefinitions.ts b/packages/cli/src/lib/builder/buildTypeDefinitions.ts index 85e54850e4..3bf3a4495f 100644 --- a/packages/cli/src/lib/builder/buildTypeDefinitions.ts +++ b/packages/cli/src/lib/builder/buildTypeDefinitions.ts @@ -16,10 +16,10 @@ import fs from 'fs-extra'; import chalk from 'chalk'; -import { Worker } from 'worker_threads'; import { relative as relativePath, resolve as resolvePath } from 'path'; import { paths } from '../paths'; import { buildTypeDefinitionsWorker } from './buildTypeDefinitionsWorker'; +import { runWorkerThreads } from '../parallel'; // These message types are ignored since we want to avoid duplicating the logic of // handling them correctly, and we already have the API Reports warning about them. @@ -84,59 +84,46 @@ export async function buildTypeDefinitions( const typescriptDir = paths.resolveTargetRoot('node_modules/typescript'); const hasTypescript = await fs.pathExists(typescriptDir); const typescriptCompilerFolder = hasTypescript ? typescriptDir : undefined; - - const worker = new Worker(`(${buildTypeDefinitionsWorker})()`, { - eval: true, + await runWorkerThreads({ + threadCount: 1, workerData: { entryPoints, workerConfigs, typescriptCompilerFolder, }, - }); - - await new Promise((resolve, reject) => { - worker.once('error', reject); - worker.once('exit', code => { - if (code) { - reject(new Error(`Worker exited with code ${code}`)); + worker: buildTypeDefinitionsWorker, + onMessage: ({ + message, + targetTypesDir, + }: { + message: any; + targetTypesDir: string; + }) => { + if (ignoredMessages.has(message.messageId)) { + return; } - }); - worker.on('message', data => { - if (data.type === 'done') { - if (data.error) { - reject(data.error); - } else { - resolve(); - } - } else if (data.type === 'message') { - const { message, targetTypesDir } = data; - if (ignoredMessages.has(message.messageId)) { - return; - } - - let text = `${message.text} (${message.messageId})`; - if (message.sourceFilePath) { - text += ' at '; - text += relativePath(targetTypesDir, message.sourceFilePath); - if (message.sourceFileLine) { - text += `:${message.sourceFileLine}`; - if (message.sourceFileColumn) { - text += `:${message.sourceFileColumn}`; - } + let text = `${message.text} (${message.messageId})`; + if (message.sourceFilePath) { + text += ' at '; + text += relativePath(targetTypesDir, message.sourceFilePath); + if (message.sourceFileLine) { + text += `:${message.sourceFileLine}`; + if (message.sourceFileColumn) { + text += `:${message.sourceFileColumn}`; } } - if (message.logLevel === 'error') { - console.error(chalk.red(`Error: ${text}`)); - } else if ( - message.logLevel === 'warning' || - message.category === 'Extractor' - ) { - console.warn(`Warning: ${text}`); - } else { - console.log(text); - } } - }); + if (message.logLevel === 'error') { + console.error(chalk.red(`Error: ${text}`)); + } else if ( + message.logLevel === 'warning' || + message.category === 'Extractor' + ) { + console.warn(`Warning: ${text}`); + } else { + console.log(text); + } + }, }); } diff --git a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts index 8cb843f58e..43e5cbc526 100644 --- a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts +++ b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts @@ -20,7 +20,10 @@ * be self-contained. * Using TypeScript is fine as it is transpiled before being stringified. */ -export function buildTypeDefinitionsWorker() { +export async function buildTypeDefinitionsWorker( + workerData: any, + sendMessage: (message: any) => void, +) { try { require('@microsoft/api-extractor'); } catch (error) { @@ -31,7 +34,6 @@ export function buildTypeDefinitionsWorker() { } const { dirname } = require('path'); - const { workerData, parentPort } = require('worker_threads'); const { entryPoints, workerConfigs, typescriptCompilerFolder } = workerData; const apiExtractor = require('@microsoft/api-extractor'); @@ -63,7 +65,6 @@ export function buildTypeDefinitionsWorker() { return old.call(this, path); }; - let success = true; let compilerState; for (const { extractorOptions, targetTypesDir } of workerConfigs) { const extractorConfig = ExtractorConfig.prepare(extractorOptions); @@ -82,24 +83,15 @@ export function buildTypeDefinitionsWorker() { showDiagnostics: false, messageCallback: (message: any) => { message.handled = true; - parentPort.postMessage({ type: 'message', message, targetTypesDir }); + sendMessage({ message, targetTypesDir }); }, }); if (!extractorResult.succeeded) { - parentPort.postMessage({ - type: 'done', - error: new Error( - `Type definition build completed with ${extractorResult.errorCount} errors` + - ` and ${extractorResult.warningCount} warnings`, - ), - }); - success = false; - break; + throw new Error( + `Type definition build completed with ${extractorResult.errorCount} errors` + + ` and ${extractorResult.warningCount} warnings`, + ); } } - - if (success) { - parentPort.postMessage({ type: 'done' }); - } } diff --git a/packages/cli/src/lib/diff/handlers.ts b/packages/cli/src/lib/diff/handlers.ts index 5bd90e3d22..55e9cddd3d 100644 --- a/packages/cli/src/lib/diff/handlers.ts +++ b/packages/cli/src/lib/diff/handlers.ts @@ -173,6 +173,14 @@ class PackageJsonHandler { return; } + // Skip diffing package scripts that have been migrated to the new commands + const hasNewScript = Object.values(targetScripts).some(script => + String(script).includes('backstage-cli package '), + ); + if (hasNewScript) { + return; + } + for (const key of Object.keys(pkgScripts)) { await this.syncField(key, pkgScripts, targetScripts, 'scripts'); } diff --git a/packages/cli/src/lib/git.test.ts b/packages/cli/src/lib/git.test.ts new file mode 100644 index 0000000000..2e5d464796 --- /dev/null +++ b/packages/cli/src/lib/git.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { runGit, listChangedFiles } from './git'; + +describe('runGit', () => { + it('runs a git command', async () => { + await expect(runGit('log', 'HEAD..HEAD')).resolves.toEqual(['']); + }); + + it('fails for unknown commands', async () => { + await expect(runGit('ryckbegΓ€ran')).rejects.toThrow( + /^git ryckbegΓ€ran failed, git: 'ryckbegΓ€ran' is not a git command/, + ); + }); + + it('forwards failures', async () => { + await expect( + runGit( + 'show', + '--quiet', + '--pretty=format:%s', + '0000000000000000000000000000000000000000', + ), + ).rejects.toThrow( + 'git show failed, fatal: bad object 0000000000000000000000000000000000000000', + ); + }); +}); + +describe('listChangedFiles', () => { + it('requires a ref', async () => { + await expect(listChangedFiles('')).rejects.toThrow('ref is required'); + }); + + it('should return something', async () => { + await expect(listChangedFiles('HEAD')).resolves.toEqual(expect.any(Array)); + }); +}); diff --git a/packages/cli/src/lib/git.ts b/packages/cli/src/lib/git.ts new file mode 100644 index 0000000000..f8783804d1 --- /dev/null +++ b/packages/cli/src/lib/git.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { assertError, ForwardedError } from '@backstage/errors'; +import { execFile as execFileCb } from 'child_process'; +import { promisify } from 'util'; +import { paths } from './paths'; + +const execFile = promisify(execFileCb); + +/** + * Run a git command, trimming the output splitting it into lines. + */ +export async function runGit(...args: string[]) { + try { + const { stdout } = await execFile('git', args, { + shell: true, + cwd: paths.targetRoot, + }); + return stdout.trim().split(/\r\n|\r|\n/); + } catch (error) { + assertError(error); + if (error.stderr || typeof error.code === 'number') { + const stderr = (error.stderr as undefined | Buffer)?.toString('utf8'); + const msg = stderr?.trim() ?? `with exit code ${error.code}`; + throw new Error(`git ${args[0]} failed, ${msg}`); + } + throw new ForwardedError('Unknown execution error', error); + } +} + +/** + * Returns a sorted list of all files that have changed since the merge base + * of the provided `ref` and HEAD, as well as all files that are not tracked by git. + */ +export async function listChangedFiles(ref: string) { + if (!ref) { + throw new Error('ref is required'); + } + const [base] = await runGit('merge-base', 'HEAD', ref); + + const tracked = await runGit('diff', '--name-only', base); + const untracked = await runGit('ls-files', '--others', '--exclude-standard'); + + return Array.from(new Set([...tracked, ...untracked])); +} diff --git a/packages/cli/src/lib/logging.ts b/packages/cli/src/lib/logging.ts index 8745585d1e..59473d7f64 100644 --- a/packages/cli/src/lib/logging.ts +++ b/packages/cli/src/lib/logging.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -export type LogFunc = (data: Buffer | string) => void; +export type LogFunc = (data: Buffer) => void; export type LogPipe = (dst: NodeJS.WriteStream) => LogFunc; export type LogOptions = { diff --git a/packages/cli/src/lib/monorepo/PackageGraph.test.ts b/packages/cli/src/lib/monorepo/PackageGraph.test.ts index e8e531bc93..06427a7313 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.test.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.test.ts @@ -15,8 +15,20 @@ */ import { getPackages } from '@manypkg/get-packages'; -import { paths } from '../paths'; import { PackageGraph } from './PackageGraph'; +import { listChangedFiles } from '../git'; + +jest.mock('../git'); + +const mockListChangedFiles = listChangedFiles as jest.MockedFunction< + typeof listChangedFiles +>; + +jest.mock('../paths', () => ({ + paths: { + targetRoot: '/', + }, +})); const testPackages = [ { @@ -53,7 +65,7 @@ const testPackages = [ describe('PackageGraph', () => { it('is able to construct a graph from this repo', async () => { - const { packages } = await getPackages(paths.ownDir); + const { packages } = await getPackages(__dirname); const graph = PackageGraph.fromPackages(packages); expect(graph.has('@backstage/cli')).toBe(true); }); @@ -124,4 +136,24 @@ describe('PackageGraph', () => { `Package 'unknown' not found`, ); }); + + it('lists changed packages', async () => { + const graph = PackageGraph.fromPackages(testPackages); + + mockListChangedFiles.mockResolvedValueOnce( + [ + 'README.md', + 'packages/a/src/foo.ts', + 'packages/a/src/bar.ts', + 'packages/b/package.json', + 'packages/f/src/foo.ts', + 'packages/f/README.md', + 'plugins/foo/src/index.ts', + ].sort(), + ); + + await expect( + graph.listChangedPackages({ ref: 'origin/master' }), + ).resolves.toEqual([graph.get('a'), graph.get('b')]); + }); }); diff --git a/packages/cli/src/lib/monorepo/PackageGraph.ts b/packages/cli/src/lib/monorepo/PackageGraph.ts index 89d5f79cd2..4bbb9eac67 100644 --- a/packages/cli/src/lib/monorepo/PackageGraph.ts +++ b/packages/cli/src/lib/monorepo/PackageGraph.ts @@ -14,9 +14,11 @@ * limitations under the License. */ +import path from 'path'; import { getPackages, Package } from '@manypkg/get-packages'; import { paths } from '../paths'; import { PackageRole } from '../role'; +import { listChangedFiles } from '../git'; type PackageJSON = Package['packageJson']; @@ -158,4 +160,50 @@ export class PackageGraph extends Map { return targets; } + + async listChangedPackages(options: { ref: string }) { + const changedFiles = await listChangedFiles(options.ref); + + const dirMap = new Map( + Array.from(this.values()).map(pkg => [ + // relative from root, convert to posix, and add a / at the end + path + .relative(paths.targetRoot, pkg.dir) + .split(path.sep) + .join(path.posix.sep) + path.posix.sep, + pkg, + ]), + ); + const packageDirs = Array.from(dirMap.keys()); + + const result = new Array(); + let searchIndex = 0; + + changedFiles.sort(); + packageDirs.sort(); + + for (const packageDir of packageDirs) { + // Skip through changes that appear before our package dir + while ( + searchIndex < changedFiles.length && + changedFiles[searchIndex] < packageDir + ) { + searchIndex += 1; + } + + // Check if we arrived at a match, otherwise we move on to the next package dir + if (changedFiles[searchIndex]?.startsWith(packageDir)) { + searchIndex += 1; + + result.push(dirMap.get(packageDir)!); + + // Skip through the rest of the changed files for the same package + while (changedFiles[searchIndex]?.startsWith(packageDir)) { + searchIndex += 1; + } + } + } + + return result; + } } diff --git a/packages/cli/src/lib/monorepo/index.ts b/packages/cli/src/lib/monorepo/index.ts index aa12c63abc..7156975c07 100644 --- a/packages/cli/src/lib/monorepo/index.ts +++ b/packages/cli/src/lib/monorepo/index.ts @@ -15,4 +15,8 @@ */ export { PackageGraph } from './PackageGraph'; -export type { PackageGraphNode } from './PackageGraph'; +export type { + PackageGraphNode, + ExtendedPackage, + ExtendedPackageJSON, +} from './PackageGraph'; diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 15ccda30c2..bce6c5c14c 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -38,6 +38,7 @@ import { Output, } from '../builder'; import { copyPackageDist } from './copyPackageDist'; +import { getRoleInfo } from '../role'; // These packages aren't safe to pack in parallel since the CLI depends on them const UNSAFE_PACKAGES = [ @@ -131,7 +132,9 @@ export async function createDistWorkspace( } const role = pkg.packageJson.backstage?.role; if (!role) { - console.warn(`Ignored ${pkg.packageJson.name} because it has no role`); + console.warn( + `Building ${pkg.packageJson.name} separately because it has no role`, + ); customBuild.push(pkg.packageJson.name); continue; } @@ -142,9 +145,17 @@ export async function createDistWorkspace( continue; } - if (!buildScript.startsWith('backstage-cli script build')) { + if (!buildScript.startsWith('backstage-cli package build')) { console.warn( - `Ignored ${pkg.packageJson.name} because it has a custom build script, '${buildScript}'`, + `Building ${pkg.packageJson.name} separately because it has a custom build script, '${buildScript}'`, + ); + customBuild.push(pkg.packageJson.name); + continue; + } + + if (getRoleInfo(role).output.includes('bundle')) { + console.warn( + `Building ${pkg.packageJson.name} separately because it is a bundled package`, ); customBuild.push(pkg.packageJson.name); continue; @@ -216,7 +227,7 @@ export async function createDistWorkspace( const FAST_PACK_SCRIPTS = [ undefined, 'backstage-cli prepack', - 'backstage-cli script prepack', + 'backstage-cli package prepack', ]; async function moveToDistWorkspace( diff --git a/packages/cli/src/lib/parallel.test.ts b/packages/cli/src/lib/parallel.test.ts index d851f33f82..032d66afac 100644 --- a/packages/cli/src/lib/parallel.test.ts +++ b/packages/cli/src/lib/parallel.test.ts @@ -14,12 +14,17 @@ * limitations under the License. */ +import os from 'os'; import { parseParallelismOption, getEnvironmentParallelism, runParallelWorkers, + runWorkerQueueThreads, + runWorkerThreads, } from './parallel'; +const defaultParallelism = Math.ceil(os.cpus().length / 2); + describe('parseParallelismOption', () => { it('coerces false no parallelism', () => { expect(parseParallelismOption(false)).toBe(1); @@ -27,10 +32,10 @@ describe('parseParallelismOption', () => { }); it('coerces true or undefined to default parallelism', () => { - expect(parseParallelismOption(true)).toBe(4); - expect(parseParallelismOption('true')).toBe(4); - expect(parseParallelismOption(undefined)).toBe(4); - expect(parseParallelismOption(null)).toBe(4); + expect(parseParallelismOption(true)).toBe(defaultParallelism); + expect(parseParallelismOption('true')).toBe(defaultParallelism); + expect(parseParallelismOption(undefined)).toBe(defaultParallelism); + expect(parseParallelismOption(null)).toBe(defaultParallelism); }); it('coerces number string to number', () => { @@ -50,13 +55,13 @@ describe('getEnvironmentParallelism', () => { expect(getEnvironmentParallelism()).toBe(2); process.env.BACKSTAGE_CLI_BUILD_PARALLEL = 'true'; - expect(getEnvironmentParallelism()).toBe(4); + expect(getEnvironmentParallelism()).toBe(defaultParallelism); process.env.BACKSTAGE_CLI_BUILD_PARALLEL = 'false'; expect(getEnvironmentParallelism()).toBe(1); delete process.env.BACKSTAGE_CLI_BUILD_PARALLEL; - expect(getEnvironmentParallelism()).toBe(4); + expect(getEnvironmentParallelism()).toBe(defaultParallelism); }); }); @@ -68,6 +73,7 @@ describe('runParallelWorkers', () => { const work = runParallelWorkers({ items: [0, 1, 2, 3, 4], + parallelismSetting: 4, parallelismFactor: 0.5, // 2 at a time worker: async item => { started.push(item); @@ -142,3 +148,68 @@ describe('runParallelWorkers', () => { expect(done).toEqual([0, 1, 2, 3, 4]); }); }); + +describe('runWorkerQueueThreads', () => { + it('should execute work in parallel', async () => { + const sharedData = new SharedArrayBuffer(10); + const sharedView = new Uint8Array(sharedData); + + const results = await runWorkerQueueThreads({ + threadCount: 4, + workerData: sharedData, + items: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + workerFactory: data => { + const view = new Uint8Array(data); + + return async (i: number) => { + view[i] = 10 + i; + return 20 + i; + }; + }, + }); + + expect(Array.from(sharedView)).toEqual([ + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + ]); + expect(results).toEqual([20, 21, 22, 23, 24, 25, 26, 27, 28, 29]); + }); +}); + +describe('runWorkerThreads', () => { + it('should run a single thread without items', async () => { + const [result] = await runWorkerThreads({ + threadCount: 1, + workerData: 'foo', + worker: async data => `${data}bar`, + }); + + expect(result).toBe('foobar'); + }); + + it('should run multiple threads without items', async () => { + const results = await runWorkerThreads({ + threadCount: 4, + worker: async () => 'foo', + }); + + expect(results).toEqual(['foo', 'foo', 'foo', 'foo']); + }); + + it('should send messages', async () => { + const messages = new Array(); + + await runWorkerThreads({ + threadCount: 2, + worker: async (_data, sendMessage) => { + sendMessage('a'); + await new Promise(resolve => setTimeout(resolve, 10)); + sendMessage('b'); + await new Promise(resolve => setTimeout(resolve, 10)); + sendMessage('c'); + }, + onMessage: (message: string) => messages.push(message), + }); + + expect(messages.sort()).toEqual(['a', 'a', 'b', 'b', 'c', 'c']); + }); +}); diff --git a/packages/cli/src/lib/parallel.ts b/packages/cli/src/lib/parallel.ts index f8af967d22..7b4ae4609e 100644 --- a/packages/cli/src/lib/parallel.ts +++ b/packages/cli/src/lib/parallel.ts @@ -14,17 +14,21 @@ * limitations under the License. */ -export const DEFAULT_PARALLELISM = 4; +import os from 'os'; +import { ErrorLike } from '@backstage/errors'; +import { Worker } from 'worker_threads'; -export const PARALLEL_ENV_VAR = 'BACKSTAGE_CLI_BUILD_PARALLEL'; +const defaultParallelism = Math.ceil(os.cpus().length / 2); + +const PARALLEL_ENV_VAR = 'BACKSTAGE_CLI_BUILD_PARALLEL'; export type ParallelismOption = boolean | string | number | null | undefined; export function parseParallelismOption(parallel: ParallelismOption): number { if (parallel === undefined || parallel === null) { - return DEFAULT_PARALLELISM; + return defaultParallelism; } else if (typeof parallel === 'boolean') { - return parallel ? DEFAULT_PARALLELISM : 1; + return parallel ? defaultParallelism : 1; } else if (typeof parallel === 'number' && Number.isInteger(parallel)) { if (parallel < 1) { return 1; @@ -88,3 +92,249 @@ export async function runParallelWorkers( }), ); } + +type WorkerThreadMessage = + | { + type: 'done'; + } + | { + type: 'item'; + index: number; + item: unknown; + } + | { + type: 'start'; + } + | { + type: 'result'; + index: number; + result: unknown; + } + | { + type: 'error'; + error: ErrorLike; + } + | { + type: 'message'; + message: unknown; + }; + +export type WorkerQueueThreadsOptions = { + /** The items to process */ + items: Iterable; + /** + * A function that will be called within each worker thread at startup, + * which should return the worker function that will be called for each item. + * + * This function must be defined as an arrow function or using the + * function keyword, and must be entirely self contained, not referencing + * any variables outside of its scope. This is because the function source + * is stringified and evaluated in the worker thread. + * + * To pass data to the worker, use the `workerData` option and `items`, but + * note that they are both copied by value into the worker thread, except for + * types that are explicitly shareable across threads, such as `SharedArrayBuffer`. + */ + workerFactory: ( + data: TData, + ) => + | ((item: TItem) => Promise) + | Promise<(item: TItem) => Promise>; + /** Data supplied to each worker factory */ + workerData?: TData; + /** Number of threads, defaults to half of the number of available CPUs */ + threadCount?: number; +}; + +/** + * Spawns one or more worker threads using the `worker_threads` module. + * Each thread processes one item at a time from the provided `options.items`. + */ +export async function runWorkerQueueThreads( + options: WorkerQueueThreadsOptions, +): Promise { + const items = Array.from(options.items); + const { + workerFactory, + workerData, + threadCount = Math.min(getEnvironmentParallelism(), items.length), + } = options; + + const iterator = items[Symbol.iterator](); + const results = new Array(); + let itemIndex = 0; + + await Promise.all( + Array(threadCount) + .fill(0) + .map(async () => { + const thread = new Worker(`(${workerQueueThread})(${workerFactory})`, { + eval: true, + workerData, + }); + + return new Promise((resolve, reject) => { + thread.on('message', (message: WorkerThreadMessage) => { + if (message.type === 'start' || message.type === 'result') { + if (message.type === 'result') { + results[message.index] = message.result as TResult; + } + const { value, done } = iterator.next(); + if (done) { + thread.postMessage({ type: 'done' }); + } else { + thread.postMessage({ + type: 'item', + index: itemIndex, + item: value, + }); + itemIndex += 1; + } + } else if (message.type === 'error') { + const error = new Error(message.error.message); + error.name = message.error.name; + error.stack = message.error.stack; + reject(error); + } + }); + + thread.on('error', reject); + thread.on('exit', (code: number) => { + if (code !== 0) { + reject(new Error(`Worker thread exited with code ${code}`)); + } else { + resolve(); + } + }); + }); + }), + ); + + return results; +} + +function workerQueueThread( + workerFuncFactory: ( + data: unknown, + ) => Promise<(item: unknown) => Promise>, +) { + const { parentPort, workerData } = require('worker_threads'); + + Promise.resolve() + .then(() => workerFuncFactory(workerData)) + .then( + workerFunc => { + parentPort.on('message', async (message: WorkerThreadMessage) => { + if (message.type === 'done') { + parentPort.close(); + return; + } + if (message.type === 'item') { + try { + const result = await workerFunc(message.item); + parentPort.postMessage({ + type: 'result', + index: message.index, + result, + }); + } catch (error) { + parentPort.postMessage({ type: 'error', error }); + } + } + }); + + parentPort.postMessage({ type: 'start' }); + }, + error => parentPort.postMessage({ type: 'error', error }), + ); +} + +export type WorkerThreadsOptions = { + /** + * A function that is called by each worker thread to produce a result. + * + * This function must be defined as an arrow function or using the + * function keyword, and must be entirely self contained, not referencing + * any variables outside of its scope. This is because the function source + * is stringified and evaluated in the worker thread. + * + * To pass data to the worker, use the `workerData` option, but + * note that they are both copied by value into the worker thread, except for + * types that are explicitly shareable across threads, such as `SharedArrayBuffer`. + */ + worker: ( + data: TData, + sendMessage: (message: TMessage) => void, + ) => Promise; + /** Data supplied to each worker */ + workerData?: TData; + /** Number of threads, defaults to 1 */ + threadCount?: number; + /** An optional handler for messages posted from the worker thread */ + onMessage?: (message: TMessage) => void; +}; + +/** + * Spawns one or more worker threads using the `worker_threads` module. + */ +export async function runWorkerThreads( + options: WorkerThreadsOptions, +): Promise { + const { worker, workerData, threadCount = 1, onMessage } = options; + + return Promise.all( + Array(threadCount) + .fill(0) + .map(async () => { + const thread = new Worker(`(${workerThread})(${worker})`, { + eval: true, + workerData, + }); + + return new Promise((resolve, reject) => { + thread.on('message', (message: WorkerThreadMessage) => { + if (message.type === 'result') { + resolve(message.result as TResult); + } else if (message.type === 'error') { + reject(message.error); + } else if (message.type === 'message') { + onMessage?.(message.message as TMessage); + } + }); + + thread.on('error', reject); + thread.on('exit', (code: number) => { + reject( + new Error(`Unexpected worker thread exit with code ${code}`), + ); + }); + }); + }), + ); +} + +function workerThread( + workerFunc: ( + data: unknown, + sendMessage: (message: unknown) => void, + ) => Promise, +) { + const { parentPort, workerData } = require('worker_threads'); + + const sendMessage = (message: unknown) => { + parentPort.postMessage({ type: 'message', message }); + }; + + workerFunc(workerData, sendMessage).then( + result => { + parentPort.postMessage({ + type: 'result', + index: 0, + result, + }); + }, + error => { + parentPort.postMessage({ type: 'error', error }); + }, + ); +} diff --git a/packages/cli/src/lib/role/packageRoles.test.ts b/packages/cli/src/lib/role/packageRoles.test.ts index f6c9fb418a..759be462d2 100644 --- a/packages/cli/src/lib/role/packageRoles.test.ts +++ b/packages/cli/src/lib/role/packageRoles.test.ts @@ -31,8 +31,8 @@ describe('getRoleInfo', () => { output: ['types', 'esm'], }); - expect(getRoleInfo('app')).toEqual({ - role: 'app', + expect(getRoleInfo('frontend')).toEqual({ + role: 'frontend', platform: 'web', output: ['bundle'], }); @@ -56,10 +56,10 @@ describe('getRoleFromPackage', () => { expect( getRoleFromPackage({ backstage: { - role: 'app', + role: 'frontend', }, }), - ).toEqual('app'); + ).toEqual('frontend'); expect(() => getRoleFromPackage({ @@ -135,7 +135,7 @@ describe('detectRoleFromPackage', () => { 'cy:run': 'cypress run', }, }), - ).toEqual('app'); + ).toEqual('frontend'); }); it('detects the role of example-backend', () => { @@ -180,7 +180,7 @@ describe('detectRoleFromPackage', () => { clean: 'backstage-cli clean', }, }), - ).toEqual('plugin-frontend'); + ).toEqual('frontend-plugin'); }); it('detects the role of @backstage/plugin-catalog-backend', () => { @@ -204,7 +204,7 @@ describe('detectRoleFromPackage', () => { clean: 'backstage-cli clean', }, }), - ).toEqual('plugin-backend'); + ).toEqual('backend-plugin'); }); it('detects the role of @backstage/plugin-catalog-react', () => { @@ -274,7 +274,7 @@ describe('detectRoleFromPackage', () => { clean: 'backstage-cli clean', }, }), - ).toEqual('plugin-backend-module'); + ).toEqual('backend-plugin-module'); }); it('detects the role of @backstage/plugin-permission-node', () => { @@ -323,6 +323,6 @@ describe('detectRoleFromPackage', () => { clean: 'backstage-cli clean', }, }), - ).toEqual('plugin-frontend-module'); + ).toEqual('frontend-plugin-module'); }); }); diff --git a/packages/cli/src/lib/role/packageRoles.ts b/packages/cli/src/lib/role/packageRoles.ts index 7c855ee0fd..a33a7d715a 100644 --- a/packages/cli/src/lib/role/packageRoles.ts +++ b/packages/cli/src/lib/role/packageRoles.ts @@ -22,7 +22,7 @@ import { PackageRole, PackageRoleInfo } from './types'; const packageRoleInfos: PackageRoleInfo[] = [ { - role: 'app', + role: 'frontend', platform: 'web', output: ['bundle'], }, @@ -52,22 +52,22 @@ const packageRoleInfos: PackageRoleInfo[] = [ output: ['types', 'esm', 'cjs'], }, { - role: 'plugin-frontend', + role: 'frontend-plugin', platform: 'web', output: ['types', 'esm'], }, { - role: 'plugin-frontend-module', + role: 'frontend-plugin-module', platform: 'web', output: ['types', 'esm'], }, { - role: 'plugin-backend', + role: 'backend-plugin', platform: 'node', output: ['types', 'cjs'], }, { - role: 'plugin-backend-module', + role: 'backend-plugin-module', platform: 'node', output: ['types', 'cjs'], }, @@ -147,22 +147,22 @@ export function detectRoleFromPackage( const pkg = detectionSchema.parse(pkgJson); if (pkg.scripts?.start?.includes('app:serve')) { - return 'app'; + return 'frontend'; } if (pkg.scripts?.build?.includes('backend:bundle')) { return 'backend'; } if (pkg.name?.includes('plugin-') && pkg.name?.includes('-backend-module-')) { - return 'plugin-backend-module'; + return 'backend-plugin-module'; } if (pkg.name?.includes('plugin-') && pkg.name?.includes('-module-')) { - return 'plugin-frontend-module'; + return 'frontend-plugin-module'; } if (pkg.scripts?.start?.includes('plugin:serve')) { - return 'plugin-frontend'; + return 'frontend-plugin'; } if (pkg.scripts?.start?.includes('backend:dev')) { - return 'plugin-backend'; + return 'backend-plugin'; } const mainEntry = pkg.publishConfig?.main || pkg.main; diff --git a/packages/cli/src/lib/role/types.ts b/packages/cli/src/lib/role/types.ts index 6a89f7bdaf..a3961544f4 100644 --- a/packages/cli/src/lib/role/types.ts +++ b/packages/cli/src/lib/role/types.ts @@ -15,16 +15,16 @@ */ export type PackageRole = - | 'app' + | 'frontend' | 'backend' | 'cli' | 'web-library' | 'node-library' | 'common-library' - | 'plugin-frontend' - | 'plugin-frontend-module' - | 'plugin-backend' - | 'plugin-backend-module'; + | 'frontend-plugin' + | 'frontend-plugin-module' + | 'backend-plugin' + | 'backend-plugin-module'; export type PackagePlatform = 'node' | 'web' | 'common'; export type PackageOutputType = 'bundle' | 'types' | 'esm' | 'cjs'; diff --git a/packages/cli/src/lib/svgrTemplate.ts b/packages/cli/src/lib/svgrTemplate.ts index ca2a8c38fa..6af1b95e71 100644 --- a/packages/cli/src/lib/svgrTemplate.ts +++ b/packages/cli/src/lib/svgrTemplate.ts @@ -20,28 +20,23 @@ * them with .icon.svg */ export function svgrTemplate( - { template }: any, - _opts: any, - { imports, interfaces, componentName, jsx }: any, + { imports, interfaces, componentName, props, jsx }: any, + { tpl }: any, ) { - const iconName = { - ...componentName, - name: `${componentName.name.replace(/icon$/, '')}Icon`, - }; + const name = `${componentName.replace(/icon$/, '')}Icon`; const defaultExport = { type: 'ExportDefaultDeclaration', - declaration: iconName, + declaration: { type: 'Identifier', name }, }; - const typeScriptTemplate = template.smart({ plugins: ['typescript'] }); - return typeScriptTemplate.ast` + return tpl` ${imports} import SvgIcon from '@material-ui/core/SvgIcon'; ${interfaces} -const ${iconName} = props => React.createElement(SvgIcon, props, ${jsx.children}); +const ${name} = (${props}) => React.createElement(SvgIcon, ${props}, ${jsx.children}); ${defaultExport}`; } diff --git a/packages/cli/src/lib/versioning/packages.ts b/packages/cli/src/lib/versioning/packages.ts index 9f2f2bdc65..ed7266a692 100644 --- a/packages/cli/src/lib/versioning/packages.ts +++ b/packages/cli/src/lib/versioning/packages.ts @@ -67,7 +67,10 @@ export async function mapDependencies( targetDir: string, pattern: string, ): Promise> { - const { packages } = await getPackages(targetDir); + const { packages, root } = await getPackages(targetDir); + + // Include root package.json too + packages.push(root); const dependencyMap = new Map(); for (const pkg of packages) { diff --git a/packages/codemods/.snyk b/packages/codemods/.snyk new file mode 100644 index 0000000000..7926925d71 --- /dev/null +++ b/packages/codemods/.snyk @@ -0,0 +1,12 @@ +# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. +version: v1.22.1 +# ignores vulnerabilities until expiry date; change duration by modifying expiry date +ignore: + SNYK-JS-UNSETVALUE-2400660: + - '*': + reason: >- + The pollution in this vulnerability does not allow injection of + arbitrary values and is therefore a negligible risk for a CLI. + expires: 2022-08-17T21:54:43.658Z + created: 2022-02-15T21:54:43.668Z +patch: {} diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index c7283f5d8c..603fa1075e 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/codemods +## 0.1.35 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.8 + +## 0.1.34 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-app-api@0.5.3 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/cli-common@0.1.7 + ## 0.1.33 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index dc1fe6a537..9571687d74 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,12 +1,15 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.33", + "version": "0.1.34", "private": false, "publishConfig": { "access": "public", "main": "dist/index.cjs.js" }, + "backstage": { + "role": "cli" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -20,18 +23,18 @@ "main": "src/index.ts", "scripts": { "start": "nodemon --", - "build": "backstage-cli build --outputs cjs", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "prepack": "backstage-cli prepack", "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "clean": "backstage-cli package clean" }, "bin": { "backstage-codemods": "bin/backstage-codemods" }, "dependencies": { - "@backstage/cli-common": "0.1.6", + "@backstage/cli-common": "0.1.7", "@backstage/core-app-api": "*", "@backstage/core-components": "*", "@backstage/core-plugin-api": "*", diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index cf953948da..55e3aef511 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/config-loader +## 0.9.5 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/cli-common@0.1.8 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/types@0.1.3 + +## 0.9.4 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/errors@0.2.1 + - @backstage/cli-common@0.1.7 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.9.3 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index b374a02fbf..6d588d1105 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "0.9.3", + "version": "0.9.4", "private": false, "publishConfig": { "access": "public", @@ -9,6 +9,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,18 +25,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/cli-common": "^0.1.6", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/types": "^0.1.1", + "@backstage/cli-common": "^0.1.7", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/types": "^0.1.2", "@types/json-schema": "^7.0.6", "ajv": "^7.0.3", "chokidar": "^3.5.2", diff --git a/packages/config-loader/src/loader.test.ts b/packages/config-loader/src/loader.test.ts index 9faeda64ea..058f59aef1 100644 --- a/packages/config-loader/src/loader.test.ts +++ b/packages/config-loader/src/loader.test.ts @@ -333,6 +333,66 @@ describe('loadConfig', () => { stopSignal.resolve(); }); + it('watches included files', async () => { + const onChange = defer(); + const stopSignal = defer(); + + await expect( + loadConfig({ + configRoot: '/root', + configTargets: [{ path: '/root/app-config.development.yaml' }], + watch: { + onChange: onChange.resolve, + stopSignal: stopSignal.promise, + }, + }), + ).resolves.toEqual({ + appConfigs: [ + { + context: 'app-config.development.yaml', + data: { + app: { + sessionKey: 'development-key', + }, + backend: { + foo: { + bar: 'token is-secret', + }, + }, + other: { + secret: 'abc123', + }, + }, + }, + ], + }); + + // session-key is indirectly included in app-config.development.yaml + // via included.yaml + await fs.writeFile('/root/secrets/session-key.txt', 'abc234'); + + await expect(onChange.promise).resolves.toEqual([ + { + context: 'app-config.development.yaml', + data: { + app: { + sessionKey: 'development-key', + }, + backend: { + foo: { + bar: 'token is-secret', + }, + }, + other: { + secret: 'abc234', + }, + }, + }, + ]); + + stopSignal.resolve(); + }); + it('watches remote config urls', async () => { server.use(initialLoaderHandler); diff --git a/packages/config-loader/src/loader.ts b/packages/config-loader/src/loader.ts index 03a6805da0..9a3287e285 100644 --- a/packages/config-loader/src/loader.ts +++ b/packages/config-loader/src/loader.ts @@ -140,7 +140,8 @@ export async function loadConfig( const env = envFunc ?? (async (name: string) => process.env[name]); const loadConfigFiles = async () => { - const configs = []; + const fileConfigs = []; + const loadedPaths = new Set(); for (const configPath of configPaths) { if (!isAbsolute(configPath)) { @@ -148,8 +149,15 @@ export async function loadConfig( } const dir = dirname(configPath); - const readFile = (path: string) => - fs.readFile(resolvePath(dir, path), 'utf8'); + const readFile = (path: string) => { + const fullPath = resolvePath(dir, path); + // if we read a file when building configuration, + // we should include that file when watching for + // changes, too. + loadedPaths.add(fullPath); + + return fs.readFile(fullPath, 'utf8'); + }; const input = yaml.parse(await readFile(configPath)); const substitutionTransform = createSubstitutionTransform(env); @@ -158,10 +166,10 @@ export async function loadConfig( substitutionTransform, ]); - configs.push({ data, context: basename(configPath) }); + fileConfigs.push({ data, context: basename(configPath) }); } - return configs; + return { fileConfigs, loadedPaths }; }; const loadRemoteConfigFiles = async () => { @@ -199,8 +207,9 @@ export async function loadConfig( }; let fileConfigs: AppConfig[]; + let loadedPaths: Set; try { - fileConfigs = await loadConfigFiles(); + ({ fileConfigs, loadedPaths } = await loadConfigFiles()); } catch (error) { throw new ForwardedError('Failed to read static configuration file', error); } @@ -220,14 +229,24 @@ export async function loadConfig( const envConfigs = await readEnvConfig(process.env); const watchConfigFile = (watchProp: LoadConfigOptionsWatch) => { - const watcher = chokidar.watch(configPaths, { + let watchedFiles = Array.from(loadedPaths); + + const watcher = chokidar.watch(watchedFiles, { usePolling: process.env.NODE_ENV === 'test', }); let currentSerializedConfig = JSON.stringify(fileConfigs); watcher.on('change', async () => { try { - const newConfigs = await loadConfigFiles(); + const { fileConfigs: newConfigs, loadedPaths: newLoadedPaths } = + await loadConfigFiles(); + + // Replace watches to handle any added or removed + // $include or $file expressions. + watcher.unwatch(watchedFiles); + watchedFiles = Array.from(newLoadedPaths); + watcher.add(watchedFiles); + const newSerializedConfig = JSON.stringify(newConfigs); if (currentSerializedConfig === newSerializedConfig) { diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 2d3e90d1b7..2af4d3763b 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/config +## 0.1.15 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/types@0.1.3 + +## 0.1.14 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/types@0.1.2 + ## 0.1.13 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index 02c63af2b5..5b15cc7594 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "0.1.13", + "version": "0.1.14", "private": false, "publishConfig": { "access": "public", @@ -9,6 +9,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,19 +25,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/types": "^0.1.1", + "@backstage/types": "^0.1.2", "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/test-utils": "^0.2.5", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index cc115a7da2..9d7093221f 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/core-app-api +## 0.5.3 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-plugin-api@0.6.1 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + - @backstage/version-bridge@0.1.2 + ## 0.5.2 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 04e87b5d0c..894d3fcb36 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "0.5.2", + "version": "0.5.3", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,18 +24,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/types": "^0.1.1", - "@backstage/version-bridge": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/types": "^0.1.2", + "@backstage/version-bridge": "^0.1.2", "@types/prop-types": "^15.7.3", "prop-types": "^15.7.2", "react-router-dom": "6.0.0-beta.0", @@ -45,8 +49,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index fe51935ab0..b6a2468e36 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/core-components +## 0.8.9 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 126074a04b: Port supported react-use functions to react-hookz. +- Updated dependencies + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.8.8 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index ecb910c50b..7362ec9e96 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.8.8", + "version": "0.8.9", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,18 +24,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/theme": "^0.2.14", + "@backstage/config": "^0.1.14", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/theme": "^0.2.15", "@material-table/core": "^3.1.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -60,7 +64,8 @@ "react-sparklines": "^1.7.0", "react-syntax-highlighter": "^15.4.5", "react-text-truncate": "^0.17.0", - "react-use": "^17.2.4", + "react-use": "^17.3.2", + "@react-hookz/web": "^12.3.0", "react-virtualized-auto-sizer": "^1.0.6", "react-window": "^1.8.6", "remark-gfm": "^3.0.1", @@ -73,9 +78,9 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/core-app-api": "^0.5.2", - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/core-app-api": "^0.5.3", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx index 7f0069bc44..14f71984f4 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSearch.tsx @@ -15,7 +15,7 @@ */ import { useMemo, useState } from 'react'; -import useToggle from 'react-use/lib/useToggle'; +import { useToggle } from '@react-hookz/web'; import { AnsiLine } from './AnsiProcessor'; export function applySearchFilter(lines: AnsiLine[], searchText: string) { diff --git a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx index 69952d487a..da489725e4 100644 --- a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx +++ b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx @@ -18,7 +18,7 @@ import { makeStyles } from '@material-ui/core/styles'; import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip'; import React, { useState } from 'react'; import TextTruncate, { TextTruncateProps } from 'react-text-truncate'; -import useMountedState from 'react-use/lib/useMountedState'; +import { useIsMounted } from '@react-hookz/web'; type Props = { text: TextTruncateProps['text']; @@ -41,7 +41,7 @@ const useStyles = makeStyles( export function OverflowTooltip(props: Props) { const [hover, setHover] = useState(false); - const isMounted = useMountedState(); + const isMounted = useIsMounted(); const classes = useStyles(); const handleToggled = (truncated: boolean) => { diff --git a/packages/core-components/src/hooks/useQueryParamState.ts b/packages/core-components/src/hooks/useQueryParamState.ts index 72ccafd99f..16cd9e18c8 100644 --- a/packages/core-components/src/hooks/useQueryParamState.ts +++ b/packages/core-components/src/hooks/useQueryParamState.ts @@ -18,7 +18,7 @@ import { isEqual } from 'lodash'; import qs from 'qs'; import { useEffect, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; -import useDebounce from 'react-use/lib/useDebounce'; +import { useDebouncedEffect } from '@react-hookz/web'; function stringify(queryParams: any): string { // Even though these setting don't look nice (e.g. escaped brackets), we should keep @@ -75,7 +75,7 @@ export function useQueryParamState( ); }, [searchParamsString, setQueryParamState, stateName]); - useDebounce( + useDebouncedEffect( () => { const queryString = joinQueryString( searchParamsString, @@ -87,8 +87,8 @@ export function useQueryParamState( setSearchParams(queryString, { replace: true }); } }, - debounceTime, [setSearchParams, queryParamState, searchParamsString, stateName], + debounceTime, ); return [queryParamState, setQueryParamState]; diff --git a/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx index adcd6ced8f..13a61d259f 100644 --- a/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx +++ b/packages/core-components/src/layout/ProxiedSignInPage/ProxiedSignInPage.tsx @@ -20,7 +20,7 @@ import { useApi, } from '@backstage/core-plugin-api'; import React from 'react'; -import useAsync from 'react-use/lib/useAsync'; +import { useAsync, useMountEffect } from '@react-hookz/web'; import { ErrorPanel } from '../../components/ErrorPanel'; import { Progress } from '../../components/Progress'; import { ProxiedSignInIdentity } from './ProxiedSignInIdentity'; @@ -56,7 +56,7 @@ export type ProxiedSignInPageProps = SignInPageProps & { export const ProxiedSignInPage = (props: ProxiedSignInPageProps) => { const discoveryApi = useApi(discoveryApiRef); - const { loading, error } = useAsync(async () => { + const [{ status, error }, { execute }] = useAsync(async () => { const identity = new ProxiedSignInIdentity({ provider: props.provider, discoveryApi, @@ -65,9 +65,11 @@ export const ProxiedSignInPage = (props: ProxiedSignInPageProps) => { await identity.start(); props.onSignInSuccess(identity); - }, []); + }); - if (loading) { + useMountEffect(execute); + + if (status === 'loading') { return ; } else if (error) { return ( diff --git a/packages/core-components/src/layout/Sidebar/Intro.tsx b/packages/core-components/src/layout/Sidebar/Intro.tsx index 7b2c5fa4d7..1fcc54188f 100644 --- a/packages/core-components/src/layout/Sidebar/Intro.tsx +++ b/packages/core-components/src/layout/Sidebar/Intro.tsx @@ -21,7 +21,7 @@ import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; import React, { useContext, useState } from 'react'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { useLocalStorageValue } from '@react-hookz/web'; import { sidebarConfig, SidebarContext, @@ -155,7 +155,7 @@ export function SidebarIntro(_props: {}) { recentlyViewedItemsDismissed: false, }; const [dismissedIntro, setDismissedIntro] = - useLocalStorage(SIDEBAR_INTRO_LOCAL_STORAGE); + useLocalStorageValue(SIDEBAR_INTRO_LOCAL_STORAGE); const { starredItemsDismissed, recentlyViewedItemsDismissed } = dismissedIntro ?? {}; diff --git a/packages/core-components/src/layout/SignInPage/SignInPage.tsx b/packages/core-components/src/layout/SignInPage/SignInPage.tsx index 2eac16cbf4..6092f2862f 100644 --- a/packages/core-components/src/layout/SignInPage/SignInPage.tsx +++ b/packages/core-components/src/layout/SignInPage/SignInPage.tsx @@ -25,7 +25,7 @@ import Button from '@material-ui/core/Button'; import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import React, { useState } from 'react'; -import useMount from 'react-use/lib/useMount'; +import { useMountEffect } from '@react-hookz/web'; import { Progress } from '../../components/Progress'; import { Content } from '../Content/Content'; import { ContentHeader } from '../ContentHeader/ContentHeader'; @@ -149,7 +149,7 @@ export const SingleSignInPage = ({ } }; - useMount(() => login({ checkExisting: true })); + useMountEffect(() => login({ checkExisting: true })); return showLoginPage ? ( diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 21668577a1..e28b828937 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/core-plugin-api +## 0.6.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 2714145cf5: Removes unused react-use dependency. +- Updated dependencies + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + - @backstage/version-bridge@0.1.2 + ## 0.6.0 ### Minor Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index c9f110b432..dc4c884684 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "0.6.0", + "version": "0.6.1", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,21 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/types": "^0.1.1", - "@backstage/version-bridge": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/types": "^0.1.2", + "@backstage/version-bridge": "^0.1.2", "history": "^5.0.0", "prop-types": "^15.7.2", "react-router-dom": "6.0.0-beta.0", - "react-use": "^17.2.4", "zen-observable": "^0.8.15" }, "peerDependencies": { @@ -43,9 +46,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/core-app-api": "^0.5.2-next.0", - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 886d873740..b57d02daae 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/create-app +## 0.4.20 + +### Patch Changes + +- e725bb812f: Remove SearchContextProvider from `` + + The `SidebarSearchModal` exported from `plugin-search` internally renders `SearchContextProvider`, so it can be removed from `Root.tsx`: + + ```diff + -import { + - SidebarSearchModal, + - SearchContextProvider, + -} from '@backstage/plugin-search'; + +import { SidebarSearchModal } from '@backstage/plugin-search'; + + ... omitted ... + + } to="/search"> + - + - + - + + + + ``` + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/cli-common@0.1.7 + ## 0.4.19 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 991a241887..158060f2e8 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,11 +1,14 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.19", + "version": "0.4.20", "private": false, "publishConfig": { "access": "public" }, + "backstage": { + "role": "cli" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,16 +24,16 @@ "backstage-create-app": "bin/backstage-create-app" }, "scripts": { - "build": "backstage-cli build --outputs cjs", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "clean": "backstage-cli clean", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", "prepack": "node scripts/prepack.js", "postpack": "node scripts/postpack.js", "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.6", + "@backstage/cli-common": "^0.1.7", "chalk": "^4.0.0", "commander": "^6.1.0", "fs-extra": "9.1.0", @@ -48,6 +51,7 @@ "ts-node": "^10.0.0" }, "peerDependencies": { + "@backstage/app-defaults": "", "@backstage/backend-common": "", "@backstage/backend-tasks": "", "@backstage/catalog-client": "", @@ -58,30 +62,35 @@ "@backstage/core-components": "", "@backstage/core-plugin-api": "", "@backstage/errors": "", + "@backstage/integration-react": "", "@backstage/plugin-api-docs": "", "@backstage/plugin-app-backend": "", "@backstage/plugin-auth-backend": "", "@backstage/plugin-catalog": "", "@backstage/plugin-catalog-backend": "", + "@backstage/plugin-catalog-common": "", "@backstage/plugin-catalog-graph": "", "@backstage/plugin-catalog-import": "", + "@backstage/plugin-catalog-react": "", + "@backstage/plugin-circleci": "", "@backstage/plugin-explore": "", "@backstage/plugin-github-actions": "", "@backstage/plugin-lighthouse": "", + "@backstage/plugin-org": "", "@backstage/plugin-permission-common": "", "@backstage/plugin-permission-node": "", + "@backstage/plugin-permission-react": "", "@backstage/plugin-proxy-backend": "", "@backstage/plugin-rollbar-backend": "", "@backstage/plugin-scaffolder": "", + "@backstage/plugin-scaffolder-backend": "", "@backstage/plugin-search": "", "@backstage/plugin-search-backend": "", "@backstage/plugin-search-backend-node": "", - "@backstage/plugin-scaffolder-backend": "", "@backstage/plugin-tech-radar": "", "@backstage/plugin-techdocs": "", "@backstage/plugin-techdocs-backend": "", "@backstage/plugin-user-settings": "", - "@backstage/integration-react": "", "@backstage/test-utils": "", "@backstage/theme": "" }, diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx index 7e98c7d3e6..90738c44d4 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx @@ -28,10 +28,7 @@ import { Settings as SidebarSettings, UserSettingsSignInAvatar, } from '@backstage/plugin-user-settings'; -import { - SidebarSearchModal, - SearchContextProvider, -} from '@backstage/plugin-search'; +import { SidebarSearchModal } from '@backstage/plugin-search'; import { Sidebar, sidebarConfig, @@ -84,9 +81,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( } to="/search"> - - - {' '} + }> diff --git a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx index a88e7250e9..469a230ecd 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/search/SearchPage.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { makeStyles, Theme, Grid, List, Paper } from '@material-ui/core'; -import { CatalogResultListItem } from '@backstage/plugin-catalog'; +import { CatalogSearchResultListItem } from '@backstage/plugin-catalog'; import { catalogApiRef, CATALOG_FILTER_EXISTS, @@ -116,7 +116,7 @@ const SearchPage = () => { switch (type) { case 'software-catalog': return ( - diff --git a/packages/create-app/templates/default-app/packages/backend/Dockerfile b/packages/create-app/templates/default-app/packages/backend/Dockerfile index 31231a3a4a..dd35d4ddbc 100644 --- a/packages/create-app/templates/default-app/packages/backend/Dockerfile +++ b/packages/create-app/templates/default-app/packages/backend/Dockerfile @@ -9,7 +9,7 @@ # # Once the commands have been run, you can build the image using `yarn build-image` -FROM node:14-buster-slim +FROM node:16-bullseye-slim WORKDIR /app @@ -19,6 +19,12 @@ WORKDIR /app COPY yarn.lock package.json packages/backend/dist/skeleton.tar.gz ./ RUN tar xzf skeleton.tar.gz && rm skeleton.tar.gz +# install sqlite3 dependencies +RUN apt-get update && \ + apt-get install -y libsqlite3-dev python3 cmake g++ && \ + rm -rf /var/lib/apt/lists/* && \ + yarn config set python /usr/bin/python3 + RUN yarn install --frozen-lockfile --production --network-timeout 300000 && rm -rf "$(yarn cache dir)" # Then copy the rest of the backend bundle, along with any other files we might want. diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 8061f5fb98..e573a150d0 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/dev-utils +## 0.2.22 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-app-api@0.5.3 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration-react@0.1.22 + - @backstage/test-utils@0.2.5 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/app-defaults@0.1.8 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.21 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 9d55d17592..d9546b7f47 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "0.2.21", + "version": "0.2.22", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,23 +24,24 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/app-defaults": "^0.1.7", - "@backstage/core-app-api": "^0.5.2", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/test-utils": "^0.2.4", - "@backstage/theme": "^0.2.14", + "@backstage/app-defaults": "^0.1.8", + "@backstage/core-app-api": "^0.5.3", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/catalog-model": "^0.10.0", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/test-utils": "^0.2.5", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@testing-library/jest-dom": "^5.10.1", @@ -55,7 +59,7 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" }, diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index bbf55fac17..bbbeed2312 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -3,6 +3,9 @@ "description": "E2E test for verifying Backstage packages", "version": "0.2.0", "private": true, + "backstage": { + "role": "cli" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -16,9 +19,11 @@ "main": "src/index.ts", "scripts": { "start": "nodemon --", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "test:e2e": "yarn start" + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "test:e2e": "yarn start", + "build": "backstage-cli package build", + "clean": "backstage-cli package clean" }, "bin": { "e2e-test": "bin/e2e-test" diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 110863d347..0c9295532a 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/errors +## 0.2.2 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/types@0.1.3 + +## 0.2.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/types@0.1.2 + ## 0.2.0 ### Minor Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index f97adef8e1..7c284f04cc 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "0.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,20 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/types": "^0.1.1", + "@backstage/types": "^0.1.2", "cross-fetch": "^3.1.5", "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7" }, "files": [ diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index ec0457dc1e..ed1b964816 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/integration-react +## 0.1.22 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- f0e2f7a56a: Updated the `ScmAuth` error message for missing provider configurations to link to `ScmAuthApi` setup documentation. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration@0.7.3 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.1.21 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 8413442b3d..a21d72f334 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "0.1.21", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,21 +11,24 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration": "^0.7.2", - "@backstage/theme": "^0.2.14", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/integration": "^0.7.3", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,9 +38,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/packages/integration-react/src/api/ScmAuth.test.ts b/packages/integration-react/src/api/ScmAuth.test.ts index 4ebfef749e..1ad391d8d2 100644 --- a/packages/integration-react/src/api/ScmAuth.test.ts +++ b/packages/integration-react/src/api/ScmAuth.test.ts @@ -238,7 +238,7 @@ describe('ScmAuth', () => { await expect( emptyMux.getCredentials({ url: 'http://example.com' }), ).rejects.toThrow( - "No authentication provider available for access to 'http://example.com'", + "No auth provider available for 'http://example.com', see https://backstage.io/link?scm-auth", ); const scmAuth = ScmAuth.merge( @@ -256,12 +256,12 @@ describe('ScmAuth', () => { await expect( scmAuth.getCredentials({ url: 'http://not.example.com' }), ).rejects.toThrow( - "No authentication provider available for access to 'http://not.example.com'", + "No auth provider available for 'http://not.example.com', see https://backstage.io/link?scm-auth", ); await expect( scmAuth.getCredentials({ url: 'http://example.com:8080' }), ).rejects.toThrow( - "No authentication provider available for access to 'http://example.com:8080'", + "No auth provider available for 'http://example.com:8080', see https://backstage.io/link?scm-auth", ); }); }); diff --git a/packages/integration-react/src/api/ScmAuth.ts b/packages/integration-react/src/api/ScmAuth.ts index 071374e6cb..b3dab4029e 100644 --- a/packages/integration-react/src/api/ScmAuth.ts +++ b/packages/integration-react/src/api/ScmAuth.ts @@ -53,7 +53,7 @@ class ScmAuthMux implements ScmAuthApi { const provider = this.#providers.find(p => p.isUrlSupported(url)); if (!provider) { throw new Error( - `No authentication provider available for access to '${options.url}'`, + `No auth provider available for '${options.url}', see https://backstage.io/link?scm-auth`, ); } diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index f8f53e959b..963c3b5f8b 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/integration +## 0.7.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/config@0.1.15 + +## 0.7.3 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/config@0.1.14 + ## 0.7.2 ### Patch Changes @@ -212,7 +229,7 @@ - 0fd4ea443: Updates the `GithubCredentialsProvider` to return the token type, it can either be `token` or `app` depending on the authentication method. - Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4 for more info. + Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. See [this community discussion](https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4) for more info. **Removes** deprecated GithubOrgReaderProcessor provider configuration(`catalog.processors.githubOrg`). If you're using the deprecated config section make sure to migrate to [integrations](https://backstage.io/docs/integrations/github/locations) instead. diff --git a/packages/integration/package.json b/packages/integration/package.json index d6d0edd77a..81087bf4b4 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "0.7.2", + "version": "0.7.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,15 +25,15 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", + "@backstage/config": "^0.1.14", "cross-fetch": "^3.1.5", "git-url-parse": "^11.6.0", "@octokit/rest": "^18.5.3", @@ -39,9 +42,9 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/config-loader": "^0.9.3", - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/cli": "^0.14.0", + "@backstage/config-loader": "^0.9.4", + "@backstage/test-utils": "^0.2.5", "@types/jest": "^26.0.7", "@types/luxon": "^2.0.4", "msw": "^0.35.0" diff --git a/packages/integration/src/gitlab/config.ts b/packages/integration/src/gitlab/config.ts index f74b849c74..71b4cd868f 100644 --- a/packages/integration/src/gitlab/config.ts +++ b/packages/integration/src/gitlab/config.ts @@ -82,11 +82,7 @@ export function readGitLabIntegrationConfig( baseUrl = `https://${host}`; } - if (host.includes(':')) { - throw new Error( - `Invalid GitLab integration config, host '${host}' should just be the host name (e.g. "github.com"), not a URL`, - ); - } else if (!isValidHost(host)) { + if (!isValidHost(host)) { throw new Error( `Invalid GitLab integration config, '${host}' is not a valid host`, ); diff --git a/packages/integration/src/gitlab/core.ts b/packages/integration/src/gitlab/core.ts index c5b0713340..b379d3d129 100644 --- a/packages/integration/src/gitlab/core.ts +++ b/packages/integration/src/gitlab/core.ts @@ -138,7 +138,7 @@ export async function getProjectId( // Convert // to: https://gitlab.com/api/v4/projects/groupA%2Fteams%2FsubgroupA%2FteamA%2Frepo const repoIDLookup = new URL( - `${url.protocol + url.hostname}/api/v4/projects/${encodeURIComponent( + `${url.origin}/api/v4/projects/${encodeURIComponent( repo.replace(/^\//, ''), )}`, ); diff --git a/packages/release-manifests/CHANGELOG.md b/packages/release-manifests/CHANGELOG.md index 61e6c45992..61113e1c76 100644 --- a/packages/release-manifests/CHANGELOG.md +++ b/packages/release-manifests/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/release-manifests +## 0.0.2 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` + ## 0.0.1 ### Patch Changes diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json index 8ddbb73bca..7ec69a35e9 100644 --- a/packages/release-manifests/package.json +++ b/packages/release-manifests/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/release-manifests", "description": "Helper library for receiving release manifests", - "version": "0.0.1", + "version": "0.0.2", "private": false, "main": "src/index.ts", "types": "src/index.ts", @@ -11,6 +11,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,18 +25,18 @@ ], "license": "Apache-2.0", "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/test-utils": "^0.2.3", + "@backstage/test-utils": "^0.2.5", "msw": "^0.35.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32" diff --git a/packages/search-common/CHANGELOG.md b/packages/search-common/CHANGELOG.md index 4460374646..71f2952d90 100644 --- a/packages/search-common/CHANGELOG.md +++ b/packages/search-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/search-common +## 0.2.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/types@0.1.3 + - @backstage/plugin-permission-common@0.5.1 + +## 0.2.3 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/plugin-permission-common@0.5.0 + - @backstage/types@0.1.2 + ## 0.2.2 ### Patch Changes diff --git a/packages/search-common/package.json b/packages/search-common/package.json index 10b03ab663..cb5c55c8e2 100644 --- a/packages/search-common/package.json +++ b/packages/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -25,22 +28,22 @@ "dist" ], "scripts": { - "build": "backstage-cli build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "bugs": { "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/types": "^0.1.1", - "@backstage/plugin-permission-common": "^0.4.0-next.0" + "@backstage/types": "^0.1.2", + "@backstage/plugin-permission-common": "^0.5.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "jest": { "roots": [ diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 38726ce10e..ddfc161ffe 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,23 @@ # techdocs-cli-embedded-app +## 0.2.64 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.14.0 + - @backstage/core-app-api@0.5.3 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration-react@0.1.22 + - @backstage/test-utils@0.2.5 + - @backstage/plugin-catalog@0.8.0 + - @backstage/plugin-techdocs@0.13.4 + - @backstage/app-defaults@0.1.8 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.2.63 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 975bfef43b..06e8ae6f2c 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,21 +1,24 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.63", + "version": "0.2.64", "private": true, + "backstage": { + "role": "frontend" + }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^0.1.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.2", - "@backstage/config": "^0.1.13", - "@backstage/core-app-api": "^0.5.2", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/plugin-techdocs": "^0.13.3", - "@backstage/test-utils": "^0.2.4", - "@backstage/theme": "^0.2.14", + "@backstage/app-defaults": "^0.1.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/cli": "^0.14.0", + "@backstage/config": "^0.1.14", + "@backstage/core-app-api": "^0.5.3", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/plugin-techdocs": "^0.13.4", + "@backstage/test-utils": "^0.2.5", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "history": "^5.0.0", @@ -26,7 +29,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", @@ -39,11 +42,11 @@ "start-server-and-test": "^1.10.11" }, "scripts": { - "start": "backstage-cli app:serve --config ./app-config.yaml", - "build": "backstage-cli app:build --config ./app-config.yaml", - "clean": "backstage-cli clean", - "test": "backstage-cli test", - "lint": "backstage-cli lint", + "start": "backstage-cli package start --config ./app-config.yaml", + "build": "backstage-cli package build --config ./app-config.yaml", + "clean": "backstage-cli package clean", + "test": "backstage-cli package test", + "lint": "backstage-cli package lint", "test:e2e": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:dev", "test:e2e:ci": "cross-env PORT=3001 start-server-and-test start http://localhost:3001 cy:run", "cy:dev": "cypress open", diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 98015f766a..1b877774fe 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,17 @@ # @techdocs/cli +## 0.8.14 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-model@0.10.0 + - @backstage/cli-common@0.1.7 + - @backstage/config@0.1.14 + - @backstage/techdocs-common@0.11.8 + ## 0.8.13 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 19514b63d2..6ea2082388 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,11 +1,14 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "0.8.13", + "version": "0.8.14", "private": false, "publishConfig": { "access": "public" }, + "backstage": { + "role": "cli" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,10 +24,10 @@ "types": "", "scripts": { "start": "nodemon --", - "build": "backstage-cli build --outputs cjs", - "clean": "backstage-cli clean", - "lint": "backstage-cli lint", - "test": "backstage-cli test --testPathIgnorePatterns=src/e2e.test.ts", + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test --testPathIgnorePatterns=src/e2e.test.ts", "test:e2e": "backstage-cli test src/e2e.test.ts", "test:e2e:ci": "backstage-cli test --watchAll=false --ci src/e2e.test.ts", "prepack": "./scripts/prepack.sh" @@ -33,7 +36,7 @@ "techdocs-cli": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -56,11 +59,11 @@ "ext": "ts" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/cli-common": "^0.1.6", - "@backstage/config": "^0.1.13", - "@backstage/techdocs-common": "^0.11.7", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/cli-common": "^0.1.7", + "@backstage/config": "^0.1.14", + "@backstage/techdocs-common": "^0.11.8", "@types/dockerode": "^3.3.0", "commander": "^6.1.0", "dockerode": "^3.3.1", diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index d4f41cf7a3..115fe8e364 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -45,7 +45,7 @@ export function registerCommands(program: CommanderStatic) { ) .option( '--techdocs-ref ', - 'The repository hosting documentation source files e.g. github:https://ghe.mycompany.net.com/org/repo.' + + 'The repository hosting documentation source files e.g. url:https://ghe.mycompany.net.com/org/repo.' + '\nThis value is same as the backstage.io/techdocs-ref annotation of the corresponding Backstage entity.' + '\nIt is completely fine to skip this as it is only being used to set repo_url in mkdocs.yml if not found.\n', ) diff --git a/packages/techdocs-common/CHANGELOG.md b/packages/techdocs-common/CHANGELOG.md index 44fbec4171..6654850b28 100644 --- a/packages/techdocs-common/CHANGELOG.md +++ b/packages/techdocs-common/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/techdocs-common +## 0.11.9 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/search-common@0.2.4 + +## 0.11.8 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + ## 0.11.7 ### Patch Changes diff --git a/packages/techdocs-common/README.md b/packages/techdocs-common/README.md index e4889d6f79..bbaac85e9b 100644 --- a/packages/techdocs-common/README.md +++ b/packages/techdocs-common/README.md @@ -39,7 +39,7 @@ Currently the build process is split up in these three stages. - Generators - Publishers -Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `github:https://github.com/backstage/backstage.git` it will clone that repository to a temp folder and pass that on to the generator. +Preparers read your entity data and creates a working directory with your documentation source code. For example if you have set your `backstage.io/techdocs-ref` to `url:https://github.com/backstage/backstage.git` it will clone that repository to a temp folder and pass that on to the generator. Generators takes the prepared source and runs the `techdocs-container` on it. It then passes on the output folder of that build to the publisher. diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index f45f842100..f0c839b753 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/techdocs-common", "description": "Common functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "0.11.7", + "version": "0.11.8", "main": "src/index.ts", "types": "src/index.ts", "private": false, @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -25,12 +28,13 @@ "dist" ], "scripts": { - "build": "backstage-cli build --outputs cjs,types", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "bugs": { "url": "https://github.com/backstage/backstage/issues" @@ -38,12 +42,12 @@ "dependencies": { "@azure/identity": "^2.0.1", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/search-common": "^0.2.2", - "@backstage/integration": "^0.7.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/search-common": "^0.2.3", + "@backstage/integration": "^0.7.3", "@google-cloud/storage": "^5.6.0", "@trendyol-js/openstack-swift-sdk": "^0.0.5", "@types/express": "^4.17.6", @@ -60,7 +64,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/packages/techdocs-common/src/helpers.ts b/packages/techdocs-common/src/helpers.ts index 7a9e4b18be..ccf1256381 100644 --- a/packages/techdocs-common/src/helpers.ts +++ b/packages/techdocs-common/src/helpers.ts @@ -18,7 +18,7 @@ import { resolveSafeChildPath, UrlReader } from '@backstage/backend-common'; import { Entity, getEntitySourceLocation, - parseLocationReference, + parseLocationRef, } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -42,7 +42,7 @@ export const parseReferenceAnnotation = ( ); } - const { type, target } = parseLocationReference(annotation); + const { type, target } = parseLocationRef(annotation); return { type: type as RemoteProtocol, target, diff --git a/packages/techdocs-common/src/stages/prepare/dir.test.ts b/packages/techdocs-common/src/stages/prepare/dir.test.ts index 019bf51fe9..2bf3fe29fc 100644 --- a/packages/techdocs-common/src/stages/prepare/dir.test.ts +++ b/packages/techdocs-common/src/stages/prepare/dir.test.ts @@ -86,7 +86,7 @@ describe('directory preparer', () => { ); }); - it('should reject when managed-by-location is a git repository', async () => { + it('should reject when managed-by-location has an unknown type', async () => { const directoryPreparer = new DirectoryPreparer( mockConfig, logger, @@ -95,12 +95,12 @@ describe('directory preparer', () => { const mockEntity = createMockEntity({ 'backstage.io/managed-by-location': - 'github:https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + 'does-not-exist:https://github.com/backstage/backstage/blob/master/catalog-info.yaml', 'backstage.io/techdocs-ref': 'dir:./docs', }); await expect(directoryPreparer.prepare(mockEntity)).rejects.toThrow( - /Unable to resolve location type github/, + /Unable to resolve location type does-not-exist/, ); }); }); diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index 3e4c4c705b..357df73c8c 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -15,7 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; @@ -34,7 +34,7 @@ const getEntityRootDir = (entity: Entity) => { metadata: { namespace, name }, } = entity; - return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); + return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name); }; const logger = getVoidLogger(); diff --git a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts index e6fd45eed7..f1b660555e 100644 --- a/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/azureBlobStorage.test.ts @@ -15,7 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; @@ -34,7 +34,7 @@ const getEntityRootDir = (entity: Entity) => { metadata: { namespace, name }, } = entity; - return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); + return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name); }; const logger = getVoidLogger(); diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index ed35f2e445..87a38402d0 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -15,7 +15,7 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; @@ -34,7 +34,7 @@ const getEntityRootDir = (entity: Entity) => { metadata: { namespace, name }, } = entity; - return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); + return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name); }; const logger = getVoidLogger(); diff --git a/packages/techdocs-common/src/stages/publish/helpers.test.ts b/packages/techdocs-common/src/stages/publish/helpers.test.ts index 6245898586..7acdb47ea7 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.test.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.test.ts @@ -16,7 +16,7 @@ import mockFs from 'mock-fs'; import * as os from 'os'; import * as path from 'path'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { getStaleFiles, getFileTreeRecursively, @@ -189,7 +189,7 @@ describe('getCloudPathForLocalPath', () => { localPath, ); expect(remoteBucket).toBe( - `${ENTITY_DEFAULT_NAMESPACE}/component/backstage/${localPath}`, + `${DEFAULT_NAMESPACE}/component/backstage/${localPath}`, ); }); diff --git a/packages/techdocs-common/src/stages/publish/helpers.ts b/packages/techdocs-common/src/stages/publish/helpers.ts index cbecee51bc..decefae187 100644 --- a/packages/techdocs-common/src/stages/publish/helpers.ts +++ b/packages/techdocs-common/src/stages/publish/helpers.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import mime from 'mime-types'; import path from 'path'; import createLimiter from 'p-limit'; @@ -188,9 +188,9 @@ export const getCloudPathForLocalPath = ( const relativeFilePathPosix = localPath.split(path.sep).join(path.posix.sep); // The / delimiter is intentional since it represents the cloud storage and not the local file system. - const entityRootDir = `${ - entity.metadata?.namespace ?? ENTITY_DEFAULT_NAMESPACE - }/${entity.kind}/${entity.metadata.name}`; + const entityRootDir = `${entity.metadata?.namespace ?? DEFAULT_NAMESPACE}/${ + entity.kind + }/${entity.metadata.name}`; const relativeFilePathTriplet = `${entityRootDir}/${relativeFilePathPosix}`; diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts index ef06e26cfa..b240ce73da 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.test.ts @@ -18,7 +18,7 @@ import { getVoidLogger } from '@backstage/backend-common'; import { Entity, EntityName, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import express from 'express'; @@ -59,7 +59,7 @@ const getEntityRootDir = (entity: Entity) => { metadata: { namespace, name }, } = entity; - return path.join(rootDir, namespace || ENTITY_DEFAULT_NAMESPACE, kind, name); + return path.join(rootDir, namespace || DEFAULT_NAMESPACE, kind, name); }; const getPosixEntityRootDir = (entity: Entity) => { @@ -70,7 +70,7 @@ const getPosixEntityRootDir = (entity: Entity) => { return path.posix.join( '/rootDir', - namespace || ENTITY_DEFAULT_NAMESPACE, + namespace || DEFAULT_NAMESPACE, kind, name, ); diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 35c9ebfb35..ff170b03b6 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/test-utils +## 0.2.5 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-app-api@0.5.3 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/plugin-permission-react@0.3.1 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + ## 0.2.4 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 67b68e08cc..736abb87f3 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "0.2.4", + "version": "0.2.5", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,22 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-app-api": "^0.5.2", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/core-app-api": "^0.5.3", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.11.2", "@testing-library/jest-dom": "^5.10.1", @@ -51,7 +55,7 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "msw": "^0.35.0" diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index cfa6ee3633..5c3e8cf5d6 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/theme +## 0.2.15 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` + ## 0.2.14 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index 2846db2805..17404e8db0 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.2.14", + "version": "0.2.15", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,17 +24,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@material-ui/core": "^4.12.2" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md new file mode 100644 index 0000000000..238c61f68f --- /dev/null +++ b/packages/types/CHANGELOG.md @@ -0,0 +1,13 @@ +# @backstage/types + +## 0.1.3 + +### Patch Changes + +- Fix for the previous release with missing type declarations. + +## 0.1.2 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` diff --git a/packages/types/package.json b/packages/types/package.json index ae18fe519d..bc2de535a2 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/types", "description": "Common TypeScript types used within Backstage", - "version": "0.1.1", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,16 +25,16 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": {}, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@types/zen-observable": "^0.8.0", "zen-observable": "^0.8.15" }, diff --git a/packages/version-bridge/CHANGELOG.md b/packages/version-bridge/CHANGELOG.md index e079cd6c61..fe131f7987 100644 --- a/packages/version-bridge/CHANGELOG.md +++ b/packages/version-bridge/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/version-bridge +## 0.1.2 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` + ## 0.1.1 ### Patch Changes diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index 6989aec3cf..485b0417cf 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/version-bridge", "description": "Utilities used by @backstage packages to support multiple concurrent versions", - "version": "0.1.1", + "version": "0.1.2", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,19 +24,20 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli build --outputs types,esm", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2" diff --git a/plugins/airbrake-backend/.eslintrc.js b/plugins/airbrake-backend/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/airbrake-backend/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md new file mode 100644 index 0000000000..14b22aacde --- /dev/null +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -0,0 +1,13 @@ +# @backstage/plugin-airbrake-backend + +## 0.1.0 + +### Minor Changes + +- a5aebe3e30: Created the Airbrake backend plugin that proxies requests to the Airbrake API + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 diff --git a/plugins/airbrake-backend/README.md b/plugins/airbrake-backend/README.md new file mode 100644 index 0000000000..42369524d6 --- /dev/null +++ b/plugins/airbrake-backend/README.md @@ -0,0 +1,16 @@ +# airbrake-backend + +Welcome to the airbrake-backend backend plugin! + +_This plugin was created through the Backstage CLI_ + +## Getting started + +Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/airbrake-backend](http://localhost:7007/airbrake-backend). + +Here is an example endpoint: http://localhost:7007/airbrake-backend/health + +You can also serve the plugin in isolation by running `yarn start` in the plugin directory. +This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. + +It is only meant for local development. diff --git a/plugins/airbrake-backend/api-report.md b/plugins/airbrake-backend/api-report.md new file mode 100644 index 0000000000..b9e9a50e0b --- /dev/null +++ b/plugins/airbrake-backend/api-report.md @@ -0,0 +1,26 @@ +## API Report File for "@backstage/plugin-airbrake-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; +import express from 'express'; +import { Logger as Logger_2 } from 'winston'; + +// @public +export interface AirbrakeConfig { + apiKey: string; +} + +// @public +export function createRouter(options: RouterOptions): Promise; + +// @public +export function extractAirbrakeConfig(config: Config): AirbrakeConfig; + +// @public +export interface RouterOptions { + airbrakeConfig: AirbrakeConfig; + logger: Logger_2; +} +``` diff --git a/plugins/airbrake-backend/config.d.ts b/plugins/airbrake-backend/config.d.ts new file mode 100644 index 0000000000..ab6a7ef537 --- /dev/null +++ b/plugins/airbrake-backend/config.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 interface Config { + /** Configuration options for the Airbrake plugin */ + airbrake: { + /** + * The API Key to authenticate requests. More details on how to get this here: https://airbrake.io/docs/api/#authentication + */ + apiKey: string; + }; +} diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json new file mode 100644 index 0000000000..f24ae2931d --- /dev/null +++ b/plugins/airbrake-backend/package.json @@ -0,0 +1,58 @@ +{ + "name": "@backstage/plugin-airbrake-backend", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "start": "backstage-cli backend:dev", + "build": "backstage-cli backend:build", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@types/express": "*", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + "http-proxy-middleware": "^2.0.0", + "winston": "^3.2.1", + "cross-fetch": "^3.0.6", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.14.0", + "@types/http-proxy-middleware": "^0.19.3", + "@types/supertest": "^2.0.8", + "supertest": "^6.1.6", + "msw": "^0.35.0" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts", + "jest": { + "coverageThreshold": { + "global": { + "functions": 100, + "lines": 100, + "statements": 100 + } + }, + "coveragePathIgnorePatterns": [ + "standaloneServer.ts", + "index.ts", + "run.ts" + ] + } +} diff --git a/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts new file mode 100644 index 0000000000..ea39a27d11 --- /dev/null +++ b/plugins/airbrake-backend/src/config/ExtractAirbrakeConfig.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { Config } from '@backstage/config'; + +/** + * The configuration needed for the airbrake-backend plugin + * + * @public + */ +export interface AirbrakeConfig { + /** + * The API Key to authenticate requests. More details on how to get this here: https://airbrake.io/docs/api/#authentication + */ + apiKey: string; +} + +/** + * Extract the Airbrake config from a config object + * + * @public + * + * @param config - The config object to extract from + */ +export function extractAirbrakeConfig(config: Config): AirbrakeConfig { + return { + apiKey: config.getString('airbrake.apiKey'), + }; +} diff --git a/plugins/airbrake-backend/src/config/index.ts b/plugins/airbrake-backend/src/config/index.ts new file mode 100644 index 0000000000..60d60c2761 --- /dev/null +++ b/plugins/airbrake-backend/src/config/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 './ExtractAirbrakeConfig'; diff --git a/plugins/airbrake-backend/src/index.ts b/plugins/airbrake-backend/src/index.ts new file mode 100644 index 0000000000..f4ec6008c2 --- /dev/null +++ b/plugins/airbrake-backend/src/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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. + */ + +/** + * The Airbrake Backend plugin used by \@backstage/plugin-airbrake + * + * @packageDocumentation + */ + +export * from './service/router'; +export * from './config'; diff --git a/plugins/airbrake-backend/src/run.ts b/plugins/airbrake-backend/src/run.ts new file mode 100644 index 0000000000..0a3ed2b7f0 --- /dev/null +++ b/plugins/airbrake-backend/src/run.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/airbrake-backend/src/service/router.test.ts b/plugins/airbrake-backend/src/service/router.test.ts new file mode 100644 index 0000000000..60c1f52126 --- /dev/null +++ b/plugins/airbrake-backend/src/service/router.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { getVoidLogger } from '@backstage/backend-common'; +import express from 'express'; +import request from 'supertest'; +import { ConfigReader } from '@backstage/config'; +import { + createRouter, + generateAirbrakePathRewrite, + RouterOptions, +} from './router'; +import { AirbrakeConfig, extractAirbrakeConfig } from '../config'; + +describe('createRouter', () => { + let app: express.Express; + let airbrakeConfig: AirbrakeConfig; + + beforeEach(async () => { + jest.resetAllMocks(); + + const config = new ConfigReader({ + airbrake: { + apiKey: 'fakeApiKey', + }, + }); + airbrakeConfig = extractAirbrakeConfig(config); + + const router = await createRouter({ + logger: getVoidLogger(), + airbrakeConfig, + }); + app = express().use(router); + }); + + describe('GET /health', () => { + it('returns ok', async () => { + const response = await request(app).get('/health'); + + expect(response.status).toEqual(200); + expect(response.body).toEqual({ status: 'ok' }); + }); + }); + + describe('GET /api', () => { + it('appends the API Key properly with no other url parameters', () => { + const options: RouterOptions = { + logger: getVoidLogger(), + airbrakeConfig, + }; + const pathRewrite = generateAirbrakePathRewrite(options) as ( + path: string, + ) => string; + + expect(pathRewrite('/airbrake-backend/api/v4/random/endpoint')).toBe( + '/v4/random/endpoint?key=fakeApiKey', + ); + }); + + it('appends the API Key properly despite there being other URL parameters', () => { + const options: RouterOptions = { + logger: getVoidLogger(), + airbrakeConfig, + }; + const pathRewrite = generateAirbrakePathRewrite(options) as ( + path: string, + ) => string; + + expect( + pathRewrite( + '/airbrake-backend/api/v4/random/endpoint?param1=123¶m2=abc', + ), + ).toBe('/v4/random/endpoint?param1=123¶m2=abc&key=fakeApiKey'); + }); + }); +}); diff --git a/plugins/airbrake-backend/src/service/router.ts b/plugins/airbrake-backend/src/service/router.ts new file mode 100644 index 0000000000..b870eb5c13 --- /dev/null +++ b/plugins/airbrake-backend/src/service/router.ts @@ -0,0 +1,96 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { errorHandler } from '@backstage/backend-common'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; +import { createProxyMiddleware } from 'http-proxy-middleware'; +import { AirbrakeConfig } from '../config'; +import { Options } from 'http-proxy-middleware/dist/types'; + +/** + * The router options that are needed when creating a router. + * + * @public + */ +export interface RouterOptions { + /** + * A logger object + */ + logger: Logger; + + /** + * The Airbrake config obtained from {@link extractAirbrakeConfig} + */ + airbrakeConfig: AirbrakeConfig; +} + +/** + * Mainly used internally to generate the path. + * + * @internal + * + * @param options - Router options + */ +export const generateAirbrakePathRewrite = ( + options: RouterOptions, +): Options['pathRewrite'] => { + const apiKey = options.airbrakeConfig.apiKey; + + return path => { + let newPath = path.replace(/.+?(\/api)/g, ''); + if (newPath.includes('?')) { + newPath += `&key=${apiKey}`; + } else { + newPath += `?key=${apiKey}`; + } + return newPath; + }; +}; + +/** + * Create the Airbrake Router, used for making API calls to the Airbrake API. + * + * @public + * + * @param options - Router options + */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { logger } = options; + + const router = Router(); + router.use(express.json()); + + router.get('/health', (_, response) => { + logger.info('PONG!'); + response.send({ status: 'ok' }); + }); + + router.use( + '/api', + createProxyMiddleware({ + target: 'https://api.airbrake.io/api', + changeOrigin: true, + pathRewrite: generateAirbrakePathRewrite(options), + }), + ); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/airbrake-backend/src/service/standaloneServer.ts b/plugins/airbrake-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..5957dd0b7f --- /dev/null +++ b/plugins/airbrake-backend/src/service/standaloneServer.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { + createServiceBuilder, + loadBackendConfig, +} from '@backstage/backend-common'; +import { Server } from 'http'; +import { Logger } from 'winston'; +import { createRouter } from './router'; +import { extractAirbrakeConfig } from '../config'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'airbrake-backend-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + const airbrakeConfig = extractAirbrakeConfig(config); + logger.debug('Starting application server...'); + const router = await createRouter({ + logger, + airbrakeConfig, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/airbrake-backend', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/catalog/src/components/EntityPageLayout/Tabbed/index.ts b/plugins/airbrake-backend/src/setupTests.ts similarity index 94% rename from plugins/catalog/src/components/EntityPageLayout/Tabbed/index.ts rename to plugins/airbrake-backend/src/setupTests.ts index ff14fe3b2c..d3232290a7 100644 --- a/plugins/catalog/src/components/EntityPageLayout/Tabbed/index.ts +++ b/plugins/airbrake-backend/src/setupTests.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Tabbed } from './Tabbed'; + +export {}; diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index df784d0030..b5f6c14d81 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-airbrake +## 0.2.0 + +### Minor Changes + +- 9e505d20a3: API connectivity has added, but currently will only work by running it standalone on a browser with CORS disabled. + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/test-utils@0.2.5 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/dev-utils@0.2.22 + - @backstage/theme@0.2.15 + ## 0.1.3 ### Patch Changes diff --git a/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx new file mode 100644 index 0000000000..eae00c2d32 --- /dev/null +++ b/plugins/airbrake/dev/components/ApiBar/ApiBar.tsx @@ -0,0 +1,85 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { + createTheme, + makeStyles, + MuiThemeProvider, + TextField, +} from '@material-ui/core'; +import { Context } from '../ContextProvider'; + +const useStyles = makeStyles({ + root: { + display: 'flex', + gap: '1em', + flexWrap: 'wrap', + }, +}); + +const textFieldTheme = createTheme({ + palette: { + type: 'dark', + primary: { + light: '#fff', + main: '#fff', + dark: '#fff', + contrastText: '#fff', + }, + secondary: { + light: '#fff', + main: '#fff', + dark: '#fff', + contrastText: '#fff', + }, + action: { + disabled: '#fff', + }, + text: { + primary: '#fff', + secondary: '#fff', + }, + }, +}); + +export const ApiBar = () => { + const classes = useStyles(); + + return ( + + {value => ( +
+ + + value.setProjectId?.(parseInt(e.target.value, 10) || undefined) + } + /> + value.setApiKey?.(e.target.value)} + /> + +
+ )} +
+ ); +}; diff --git a/plugins/catalog/src/components/EntityPageLayout/index.ts b/plugins/airbrake/dev/components/ApiBar/index.ts similarity index 91% rename from plugins/catalog/src/components/EntityPageLayout/index.ts rename to plugins/airbrake/dev/components/ApiBar/index.ts index 549d3d8454..ff6e80d3d8 100644 --- a/plugins/catalog/src/components/EntityPageLayout/index.ts +++ b/plugins/airbrake/dev/components/ApiBar/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { EntityPageLayout } from './EntityPageLayout'; + +export { ApiBar } from './ApiBar'; diff --git a/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx b/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx new file mode 100644 index 0000000000..6d7fe0f7f2 --- /dev/null +++ b/plugins/airbrake/dev/components/ContextProvider/ContextProvider.tsx @@ -0,0 +1,48 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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, { + Dispatch, + PropsWithChildren, + SetStateAction, + useState, +} from 'react'; + +interface ContextInterface { + projectId?: number; + setProjectId?: Dispatch>; + apiKey?: string; + setApiKey?: Dispatch>; +} + +export const Context = React.createContext({}); + +export const ContextProvider = ({ children }: PropsWithChildren<{}>) => { + const [projectId, setProjectId] = useState(); + const [apiKey, setApiKey] = useState(''); + + return ( + + {children} + + ); +}; diff --git a/plugins/airbrake/dev/components/ContextProvider/index.ts b/plugins/airbrake/dev/components/ContextProvider/index.ts new file mode 100644 index 0000000000..f1e350868a --- /dev/null +++ b/plugins/airbrake/dev/components/ContextProvider/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { ContextProvider, Context } from './ContextProvider'; diff --git a/plugins/airbrake/dev/index.tsx b/plugins/airbrake/dev/index.tsx index e74ce68ee5..cd0d29301f 100644 --- a/plugins/airbrake/dev/index.tsx +++ b/plugins/airbrake/dev/index.tsx @@ -15,39 +15,67 @@ */ import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; -import { EntityAirbrakeContent, airbrakePlugin } from '../src/plugin'; +import { TestApiProvider } from '@backstage/test-utils'; +import { airbrakePlugin, EntityAirbrakeContent } from '../src'; import { - Content, - ContentHeader, - Header, - HeaderLabel, - Page, - SupportButton, -} from '@backstage/core-components'; + airbrakeApiRef, + MockAirbrakeApi, + ProductionAirbrakeApi, +} from '../src/api'; +import { ApiBar } from './components/ApiBar'; +import { Content, Header, Page } from '@backstage/core-components'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { createEntity } from '../src/api/mock/MockEntity'; +import CloudOffIcon from '@material-ui/icons/CloudOff'; +import CloudIcon from '@material-ui/icons/Cloud'; +import { Context, ContextProvider } from './components/ContextProvider'; createDevApp() .registerPlugin(airbrakePlugin) .addPage({ element: ( -
- - -
+
- - - A description of your plugin goes here. - - - + + + + + ), - title: 'Root Page', - path: '/airbrake', + title: 'Mock API', + path: '/airbrake-mock-api', + icon: CloudOffIcon, + }) + .addPage({ + element: ( + + +
+ +
+ + + {value => ( + + + + + + )} + + +
+
+ ), + title: 'Real API', + path: '/airbrake-real-api', + icon: CloudIcon, }) .render(); diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 40b4787dd5..1912e59f66 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.1.3", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,43 +9,50 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/dev-utils": "^0.2.22", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/test-utils": "^0.2.5", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "react-use": "^17.2.4", - "object-hash": "^2.2.0" + "object-hash": "^2.2.0", + "react-use": "^17.2.4" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@types/object-hash": "^2.2.1", - "@backstage/app-defaults": "^0.1.7", - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/app-defaults": "^0.1.8", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", - "msw": "^0.35.0", + "@types/object-hash": "^2.2.1", "cross-fetch": "^3.1.5", + "msw": "^0.35.0", "react-router": "6.0.0-beta.0" }, "files": [ diff --git a/plugins/airbrake/src/api/AirbrakeApi.ts b/plugins/airbrake/src/api/AirbrakeApi.ts new file mode 100644 index 0000000000..a29aa3eca7 --- /dev/null +++ b/plugins/airbrake/src/api/AirbrakeApi.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { Groups } from './airbrakeGroups'; +import { createApiRef } from '@backstage/core-plugin-api'; + +export const airbrakeApiRef = createApiRef({ + id: 'plugin.airbrake.service', +}); + +export interface AirbrakeApi { + fetchGroups(projectId: string): Promise; +} diff --git a/plugins/airbrake/src/api/ProductionApi.test.ts b/plugins/airbrake/src/api/ProductionApi.test.ts new file mode 100644 index 0000000000..04bb73caf7 --- /dev/null +++ b/plugins/airbrake/src/api/ProductionApi.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { ProductionAirbrakeApi } from './ProductionApi'; +import { rest } from 'msw'; +import mockGroupsData from './mock/airbrakeGroupsApiMock.json'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; + +describe('The production Airbrake API', () => { + const productionApi = new ProductionAirbrakeApi('fakeApiKey'); + const worker = setupServer(); + setupRequestMockHandlers(worker); + + it('fetches groups using the provided project ID', async () => { + worker.use( + rest.get( + 'https://api.airbrake.io/api/v4/projects/123456/groups', + (req, res, ctx) => { + if (req.url.searchParams.get('key') === 'fakeApiKey') { + return res(ctx.status(200), ctx.json(mockGroupsData)); + } + return res(ctx.status(401)); + }, + ), + ); + + const groups = await productionApi.fetchGroups('123456'); + + expect(groups).toStrictEqual(mockGroupsData); + }); + + it('throws if fetching groups was unsuccessful', async () => { + worker.use( + rest.get( + 'https://api.airbrake.io/api/v4/projects/123456/groups', + (_, res, ctx) => { + return res(ctx.status(500)); + }, + ), + ); + + await expect(productionApi.fetchGroups('123456')).rejects.toThrow(); + }); +}); diff --git a/plugins/catalog-backend/src/util/timing.ts b/plugins/airbrake/src/api/ProductionApi.ts similarity index 51% rename from plugins/catalog-backend/src/util/timing.ts rename to plugins/airbrake/src/api/ProductionApi.ts index b5f9eb258f..76416bc173 100644 --- a/plugins/catalog-backend/src/util/timing.ts +++ b/plugins/airbrake/src/api/ProductionApi.ts @@ -14,18 +14,21 @@ * limitations under the License. */ -/** - * Returns a string with the elapsed time since the start of an operation, - * with some human friendly precision, e.g. "133ms" or "14.5s". - * - * @param startTimestamp - The timestamp (from process.hrtime()) at the start ot - * the operation - */ -export function durationText(startTimestamp: [number, number]): string { - const delta = process.hrtime(startTimestamp); - const seconds = delta[0] + delta[1] / 1e9; - if (seconds > 1) { - return `${seconds.toFixed(1)}s`; +import { Groups } from './airbrakeGroups'; +import { AirbrakeApi } from './AirbrakeApi'; + +export class ProductionAirbrakeApi implements AirbrakeApi { + constructor(private readonly apiKey?: string) {} + + async fetchGroups(projectId: string): Promise { + const apiUrl = `https://api.airbrake.io/api/v4/projects/${projectId}/groups?key=${this.apiKey}`; + + const response = await fetch(apiUrl); + + if (response.status >= 400 && response.status < 600) { + throw new Error('Failed fetching Airbrake groups'); + } + + return (await response.json()) as Groups; } - return `${(seconds * 1000).toFixed(0)}ms`; } diff --git a/plugins/airbrake/src/api/airbrakeGroups.d.ts b/plugins/airbrake/src/api/airbrakeGroups.d.ts new file mode 100644 index 0000000000..e1887eca9b --- /dev/null +++ b/plugins/airbrake/src/api/airbrakeGroups.d.ts @@ -0,0 +1,65 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 interface Groups { + count: number; + end: string; + groups?: Group[] | null; + page: number; + resolvedCount: number; + unresolvedCount: number; +} + +export interface Group { + id: string; + projectId: number; + resolved: boolean; + muted: boolean; + mutedBy: number; + mutedAt?: string | null; + errors?: Error[]; + attributes?: string | null; + context: Context; + lastDeployId: string; + lastDeployAt?: string | null; + lastNoticeId: string; + lastNoticeAt: string; + noticeCount: number; + noticeTotalCount: number; + commentCount: number; + createdAt: string; +} + +export interface Error { + type: string; + message: string; + backtrace?: Backtrace[]; +} + +export interface Backtrace { + file: string; + function: string; + line: number; + column: number; + code?: string | null; +} + +export interface Context { + action: string; + component: string; + environment: string; + severity: string; +} diff --git a/plugins/airbrake/src/api/index.ts b/plugins/airbrake/src/api/index.ts new file mode 100644 index 0000000000..2d92789653 --- /dev/null +++ b/plugins/airbrake/src/api/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 './mock'; +export type { AirbrakeApi } from './AirbrakeApi'; +export { airbrakeApiRef } from './AirbrakeApi'; +export type { Groups } from './airbrakeGroups'; +export { ProductionAirbrakeApi } from './ProductionApi'; diff --git a/plugins/airbrake/src/api/mock/MockApi.ts b/plugins/airbrake/src/api/mock/MockApi.ts new file mode 100644 index 0000000000..dbb1d5c049 --- /dev/null +++ b/plugins/airbrake/src/api/mock/MockApi.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { Groups } from '../airbrakeGroups'; +import { AirbrakeApi } from '../AirbrakeApi'; +import mockGroupsData from './airbrakeGroupsApiMock.json'; + +export class MockAirbrakeApi implements AirbrakeApi { + waitTimeInMillis: number; + + constructor(waitTimeInMillis = 10) { + this.waitTimeInMillis = waitTimeInMillis; + } + + fetchGroups(): Promise { + return new Promise(resolve => { + setTimeout(() => resolve(mockGroupsData), this.waitTimeInMillis); + }); + } +} diff --git a/plugins/airbrake/src/EntityAirbrakeContent.test.tsx b/plugins/airbrake/src/api/mock/MockEntity.ts similarity index 52% rename from plugins/airbrake/src/EntityAirbrakeContent.test.tsx rename to plugins/airbrake/src/api/mock/MockEntity.ts index f0afef425f..13534f2458 100644 --- a/plugins/airbrake/src/EntityAirbrakeContent.test.tsx +++ b/plugins/airbrake/src/api/mock/MockEntity.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2022 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; -import { EntityAirbrakeContent } from './plugin'; -import { renderInTestApp } from '@backstage/test-utils'; +import { AIRBRAKE_PROJECT_ID_ANNOTATION } from '../../components/useProjectId'; +import { Entity } from '@backstage/catalog-model'; -describe('The Airbrake entity', () => { - it('should render the content properly', async () => { - const rendered = await renderInTestApp(); - expect(rendered.getByText('ChunkLoadError')).toBeInTheDocument(); - }); -}); +export const createEntity = (projectId?: number) => { + const projectIdString = projectId?.toString(); + + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + annotations: { + [AIRBRAKE_PROJECT_ID_ANNOTATION]: projectIdString, + }, + name: projectIdString, + }, + } as Entity; +}; diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json b/plugins/airbrake/src/api/mock/airbrakeGroupsApiMock.json similarity index 100% rename from plugins/airbrake/src/components/EntityAirbrakeContent/example-data.json rename to plugins/airbrake/src/api/mock/airbrakeGroupsApiMock.json diff --git a/plugins/scaffolder-backend/src/lib/catalog/index.ts b/plugins/airbrake/src/api/mock/index.ts similarity index 90% rename from plugins/scaffolder-backend/src/lib/catalog/index.ts rename to plugins/airbrake/src/api/mock/index.ts index ea693b00b3..0588d45fa6 100644 --- a/plugins/scaffolder-backend/src/lib/catalog/index.ts +++ b/plugins/airbrake/src/api/mock/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CatalogEntityClient } from './CatalogEntityClient'; + +export { MockAirbrakeApi } from './MockApi'; diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx deleted file mode 100644 index a621eb281c..0000000000 --- a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.test.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { EntityAirbrakeContent } from './EntityAirbrakeContent'; -import exampleData from './example-data.json'; -import { renderInTestApp } from '@backstage/test-utils'; - -describe('EntityAirbrakeContent', () => { - it('renders all errors sent from Airbrake', async () => { - const table = await renderInTestApp(); - expect(exampleData.groups.length).toBeGreaterThan(0); - for (const group of exampleData.groups) { - expect( - await table.getByText(group.errors[0].message), - ).toBeInTheDocument(); - } - }); -}); diff --git a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx b/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx deleted file mode 100644 index 062d9e898a..0000000000 --- a/plugins/airbrake/src/components/EntityAirbrakeContent/EntityAirbrakeContent.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { Grid, Typography } from '@material-ui/core'; -import { InfoCard } from '@backstage/core-components'; -import exampleData from './example-data.json'; -import hash from 'object-hash'; -import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; - -const useStyles = makeStyles(() => ({ - multilineText: { - whiteSpace: 'pre-wrap', - }, -})); - -export const EntityAirbrakeContent = () => { - const classes = useStyles(); - - return ( - - {exampleData.groups.map(group => ( - - {group.errors.map(error => ( - - - {error.message} - - - ))} - - ))} - - ); -}; diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx new file mode 100644 index 0000000000..ef1ac229c9 --- /dev/null +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.test.tsx @@ -0,0 +1,95 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { EntityAirbrakeWidget } from './EntityAirbrakeWidget'; +import exampleData from '../../api/mock/airbrakeGroupsApiMock.json'; +import { + MockErrorApi, + renderInTestApp, + setupRequestMockHandlers, + TestApiProvider, +} from '@backstage/test-utils'; +import { createEntity } from '../../api/mock/MockEntity'; +import { + airbrakeApiRef, + MockAirbrakeApi, + ProductionAirbrakeApi, +} from '../../api'; +import { errorApiRef } from '@backstage/core-plugin-api'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; + +describe('EntityAirbrakeContent', () => { + const worker = setupServer(); + setupRequestMockHandlers(worker); + + it('renders all errors sent from Airbrake', async () => { + const widget = await renderInTestApp( + + + , + ); + expect(exampleData.groups.length).toBeGreaterThan(0); + for (const group of exampleData.groups) { + expect( + await widget.getByText(group.errors[0].message), + ).toBeInTheDocument(); + } + }); + + it('states that the annotation is missing if no project ID annotation is provided', async () => { + const widget = await renderInTestApp( + + + , + ); + await expect( + widget.findByText('Missing Annotation'), + ).resolves.toBeInTheDocument(); + }); + + it('states that an error occurred if the API call fails', async () => { + worker.use( + rest.get( + 'https://api.airbrake.io/api/v4/projects/123/groups', + (_, res, ctx) => { + return res(ctx.status(500)); + }, + ), + ); + const mockErrorApi = new MockErrorApi({ collect: true }); + + const widget = await renderInTestApp( + + + , + ); + + await expect( + widget.findByText(/.*there was an issue communicating with Airbrake.*/), + ).resolves.toBeInTheDocument(); + expect(mockErrorApi.getErrors().length).toBe(1); + expect(mockErrorApi.getErrors()[0].error.message).toStrictEqual( + 'Failed fetching Airbrake groups', + ); + }); +}); diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx new file mode 100644 index 0000000000..b11116aeef --- /dev/null +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 React, { useEffect } from 'react'; +import { Grid, Typography } from '@material-ui/core'; +import { + EmptyState, + InfoCard, + MissingAnnotationEmptyState, + Progress, +} from '@backstage/core-components'; +import hash from 'object-hash'; +import { makeStyles } from '@material-ui/core/styles'; +import { BackstageTheme } from '@backstage/theme'; +import { ErrorApi, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { airbrakeApiRef } from '../../api'; +import useAsync from 'react-use/lib/useAsync'; +import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; + +const useStyles = makeStyles(() => ({ + multilineText: { + whiteSpace: 'pre-wrap', + }, +})); + +export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { + const classes = useStyles(); + + const projectId = useProjectId(entity); + const errorApi = useApi(errorApiRef); + const airbrakeApi = useApi(airbrakeApiRef); + + const { loading, value, error } = useAsync( + () => airbrakeApi.fetchGroups(projectId), + [airbrakeApi, projectId], + ); + + useEffect(() => { + if (error) { + errorApi.post(error); + } + }, [error, errorApi]); + + if (loading || !projectId || error) { + return ( + + {loading && } + + {!loading && !projectId && ( + + )} + + {!loading && error && ( + + )} + + ); + } + + return ( + + {value?.groups?.map(group => ( + + {group.errors?.map(groupError => ( + + + {groupError.message} + + + ))} + + ))} + + ); +}; diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/index.ts b/plugins/airbrake/src/components/EntityAirbrakeWidget/index.ts new file mode 100644 index 0000000000..0a85263c5f --- /dev/null +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { EntityAirbrakeWidget } from './EntityAirbrakeWidget'; diff --git a/plugins/airbrake/src/components/useProjectId.ts b/plugins/airbrake/src/components/useProjectId.ts new file mode 100644 index 0000000000..3402778b7b --- /dev/null +++ b/plugins/airbrake/src/components/useProjectId.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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'; + +export const AIRBRAKE_PROJECT_ID_ANNOTATION = 'airbrake.io/project-id'; + +export const useProjectId = (entity: Entity) => { + return entity?.metadata.annotations?.[AIRBRAKE_PROJECT_ID_ANNOTATION] ?? ''; +}; diff --git a/plugins/airbrake/src/extensions.test.tsx b/plugins/airbrake/src/extensions.test.tsx new file mode 100644 index 0000000000..d677d939a4 --- /dev/null +++ b/plugins/airbrake/src/extensions.test.tsx @@ -0,0 +1,37 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { EntityAirbrakeContent } from './extensions'; +import { Route } from 'react-router'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { airbrakeApiRef, MockAirbrakeApi } from './api'; +import { createEntity } from './api/mock/MockEntity'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; + +describe('The Airbrake entity', () => { + it('should render the content properly', async () => { + const rendered = await renderInTestApp( + + + } /> + + , + ); + await expect( + rendered.findByText('ChunkLoadError'), + ).resolves.toBeInTheDocument(); + }); +}); diff --git a/plugins/airbrake/src/extensions.tsx b/plugins/airbrake/src/extensions.tsx new file mode 100644 index 0000000000..6fbea68409 --- /dev/null +++ b/plugins/airbrake/src/extensions.tsx @@ -0,0 +1,37 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 { useEntity } from '@backstage/plugin-catalog-react'; +import React from 'react'; +import { airbrakePlugin } from './plugin'; +import { createRoutableExtension } from '@backstage/core-plugin-api'; +import { rootRouteRef } from './routes'; + +export const EntityAirbrakeContent = airbrakePlugin.provide( + createRoutableExtension({ + name: 'EntityAirbrakeContent', + mountPoint: rootRouteRef, + component: () => + import('./components/EntityAirbrakeWidget').then( + ({ EntityAirbrakeWidget }) => { + return () => { + const { entity } = useEntity(); + return ; + }; + }, + ), + }), +); diff --git a/plugins/airbrake/src/index.ts b/plugins/airbrake/src/index.ts index 8f319e02fd..d5aedd9ba6 100644 --- a/plugins/airbrake/src/index.ts +++ b/plugins/airbrake/src/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { airbrakePlugin, EntityAirbrakeContent } from './plugin'; +export { airbrakePlugin } from './plugin'; +export { EntityAirbrakeContent } from './extensions'; diff --git a/plugins/airbrake/src/plugin.test.ts b/plugins/airbrake/src/plugin.test.ts index c8e9c30e83..ad7865713f 100644 --- a/plugins/airbrake/src/plugin.test.ts +++ b/plugins/airbrake/src/plugin.test.ts @@ -15,9 +15,16 @@ */ import { airbrakePlugin } from './plugin'; +import { ProductionAirbrakeApi } from './api'; describe('catalog', () => { it('should export plugin', () => { expect(airbrakePlugin).toBeDefined(); }); + + it('should have at least one API, the production API', () => { + const apiFactories = Array.from(airbrakePlugin.getApis()); + expect(apiFactories.length).toBe(1); + expect(apiFactories[0].factory({})).toBeInstanceOf(ProductionAirbrakeApi); + }); }); diff --git a/plugins/airbrake/src/plugin.ts b/plugins/airbrake/src/plugin.ts index 0a3679baa4..f008b48ad4 100644 --- a/plugins/airbrake/src/plugin.ts +++ b/plugins/airbrake/src/plugin.ts @@ -13,27 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - createPlugin, - createRoutableExtension, -} from '@backstage/core-plugin-api'; +import { createApiFactory, createPlugin } from '@backstage/core-plugin-api'; import { rootRouteRef } from './routes'; +import { airbrakeApiRef, ProductionAirbrakeApi } from './api'; export const airbrakePlugin = createPlugin({ id: 'airbrake', + apis: [ + createApiFactory({ + api: airbrakeApiRef, + deps: {}, + factory: () => new ProductionAirbrakeApi(), + }), + ], routes: { root: rootRouteRef, }, }); - -export const EntityAirbrakeContent = airbrakePlugin.provide( - createRoutableExtension({ - name: 'EntityAirbrakeContent', - component: () => - import('./components/EntityAirbrakeContent/EntityAirbrakeContent').then( - m => m.EntityAirbrakeContent, - ), - mountPoint: rootRouteRef, - }), -); diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 9f5d2cc730..981e120a7a 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-allure +## 0.1.15 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.1.14 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 5ea3129746..089b58e820 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,22 +11,25 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -37,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index e24ea89a0a..a365bf98a0 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-analytics-module-ga +## 0.1.10 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.1.9 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 0b0c3a6cdc..56f2d26615 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.9", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,21 +10,24 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin-module" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +38,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 03bef4543a..ae4ebeff84 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-apache-airflow +## 0.1.7 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + ## 0.1.6 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index e36e925fcb..061f375540 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,19 +9,22 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -33,10 +36,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 73de279056..1de39bc9b8 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-api-docs +## 0.7.3 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog@0.8.0 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.7.2 ### Patch Changes diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index b626da89a5..b6683d9b40 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -9,7 +9,6 @@ import { ApiEntity } from '@backstage/catalog-model'; import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { CatalogTableRow } from '@backstage/plugin-catalog'; -import { Entity } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -17,11 +16,10 @@ import { TableColumn } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; import { UserListFilterKind } from '@backstage/plugin-catalog-react'; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ApiDefinitionCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ApiDefinitionCard: (_: Props) => JSX.Element; +export const ApiDefinitionCard: () => JSX.Element; // Warning: (ae-missing-release-tag) "ApiDefinitionWidget" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -92,13 +90,13 @@ export type AsyncApiDefinitionWidgetProps = { // Warning: (ae-missing-release-tag) "ConsumedApisCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ConsumedApisCard: ({ variant }: Props_2) => JSX.Element; +export const ConsumedApisCard: ({ variant }: Props) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ConsumingComponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ConsumingComponentsCard: ({ variant }: Props_5) => JSX.Element; +export const ConsumingComponentsCard: ({ variant }: Props_4) => JSX.Element; // @public export const DefaultApiExplorerPage: ({ @@ -122,9 +120,7 @@ export function defaultDefinitionWidgets(): ApiDefinitionWidget[]; // Warning: (ae-missing-release-tag) "EntityApiDefinitionCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityApiDefinitionCard: (_: { - apiEntity?: ApiEntity | undefined; -}) => JSX.Element; +export const EntityApiDefinitionCard: () => JSX.Element; // Warning: (ae-missing-release-tag) "EntityConsumedApisCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -132,7 +128,6 @@ export const EntityApiDefinitionCard: (_: { export const EntityConsumedApisCard: ({ variant, }: { - entity?: Entity | undefined; variant?: 'gridItem' | undefined; }) => JSX.Element; @@ -142,7 +137,6 @@ export const EntityConsumedApisCard: ({ export const EntityConsumingComponentsCard: ({ variant, }: { - entity?: Entity | undefined; variant?: 'gridItem' | undefined; }) => JSX.Element; @@ -161,7 +155,6 @@ export const EntityHasApisCard: ({ export const EntityProvidedApisCard: ({ variant, }: { - entity?: Entity | undefined; variant?: 'gridItem' | undefined; }) => JSX.Element; @@ -171,7 +164,6 @@ export const EntityProvidedApisCard: ({ export const EntityProvidingComponentsCard: ({ variant, }: { - entity?: Entity | undefined; variant?: 'gridItem' | undefined; }) => JSX.Element; @@ -193,7 +185,7 @@ export type GraphQlDefinitionWidgetProps = { // Warning: (ae-missing-release-tag) "HasApisCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const HasApisCard: ({ variant }: Props_3) => JSX.Element; +export const HasApisCard: ({ variant }: Props_2) => JSX.Element; // Warning: (ae-missing-release-tag) "OpenApiDefinitionWidget" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -228,11 +220,11 @@ export type PlainApiDefinitionWidgetProps = { // Warning: (ae-missing-release-tag) "ProvidedApisCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ProvidedApisCard: ({ variant }: Props_4) => JSX.Element; +export const ProvidedApisCard: ({ variant }: Props_3) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ProvidingComponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const ProvidingComponentsCard: ({ variant }: Props_6) => JSX.Element; +export const ProvidingComponentsCard: ({ variant }: Props_5) => JSX.Element; ``` diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 3b92cdf17e..7c61c65423 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.7.2", + "version": "0.7.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -20,23 +23,23 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { "@asyncapi/react-component": "1.0.0-next.32", - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,10 +56,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx index 6f3e155816..353b973626 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx @@ -24,12 +24,7 @@ import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; import { CardTab, TabbedCard } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - apiEntity?: ApiEntity; -}; - -export const ApiDefinitionCard = (_: Props) => { +export const ApiDefinitionCard = () => { const { entity } = useEntity(); const config = useApi(apiDocsConfigRef); const { getApiDefinitionWidget } = config; diff --git a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx index 9e4c861e24..18222eea3a 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/DefaultApiExplorerPage.test.tsx @@ -56,8 +56,8 @@ describe('DefaultApiExplorerPage', () => { }, ] as Entity[], }), - getLocationByEntity: () => - Promise.resolve({ id: 'id', type: 'github', target: 'url' }), + getLocationByRef: () => + Promise.resolve({ id: 'id', type: 'url', target: 'url' }), getEntityByName: async entityName => { return { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx index 5e7b22524a..d04a36770d 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.test.tsx @@ -36,7 +36,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx index 56b8559537..e810e06ff7 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - ApiEntity, - Entity, - RELATION_CONSUMES_API, -} from '@backstage/catalog-model'; +import { ApiEntity, RELATION_CONSUMES_API } from '@backstage/catalog-model'; import { Typography } from '@material-ui/core'; import { EntityTable, @@ -36,8 +32,6 @@ import { } from '@backstage/core-components'; type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; variant?: 'gridItem'; }; diff --git a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx index 4102bebf0e..050eeb8707 100644 --- a/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/HasApisCard.test.tsx @@ -36,7 +36,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx index b29075aee9..34043c519b 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.test.tsx @@ -36,7 +36,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx index efdc88b2e1..a63546176f 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - ApiEntity, - Entity, - RELATION_PROVIDES_API, -} from '@backstage/catalog-model'; +import { ApiEntity, RELATION_PROVIDES_API } from '@backstage/catalog-model'; import { Typography } from '@material-ui/core'; import { EntityTable, @@ -36,8 +32,6 @@ import { } from '@backstage/core-components'; type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; variant?: 'gridItem'; }; diff --git a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx index 06022eec69..c81b4750bc 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.test.tsx @@ -32,7 +32,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx index 20fa7021cc..5455f37f14 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx @@ -16,7 +16,6 @@ import { ComponentEntity, - Entity, RELATION_API_CONSUMED_BY, } from '@backstage/catalog-model'; import { Typography } from '@material-ui/core'; @@ -35,8 +34,6 @@ import { } from '@backstage/core-components'; type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; variant?: 'gridItem'; }; diff --git a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx index 275338d2f9..84e45dc058 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.test.tsx @@ -32,7 +32,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx index 286a360e9a..9bcace393e 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx @@ -16,7 +16,6 @@ import { ComponentEntity, - Entity, RELATION_API_PROVIDED_BY, } from '@backstage/catalog-model'; import { Typography } from '@material-ui/core'; @@ -35,8 +34,6 @@ import { } from '@backstage/core-components'; type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; variant?: 'gridItem'; }; diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 882979326e..b80e8dc74d 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-app-backend +## 0.3.26 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/config-loader@0.9.5 + - @backstage/types@0.1.3 + +## 0.3.25 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config-loader@0.9.4 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.3.24 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 52da00fed3..908d2cff13 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.24", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,25 +24,25 @@ "backstage" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config-loader": "^0.9.3", - "@backstage/config": "^0.1.13", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/config-loader": "^0.9.4", + "@backstage/config": "^0.1.14", + "@backstage/types": "^0.1.2", "@types/express": "^4.17.6", "globby": "^11.0.0", "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", - "helmet": "^4.0.0", + "helmet": "^5.0.2", "knex": "^1.0.2", "lodash": "^4.17.21", "luxon": "^2.0.2", @@ -47,9 +50,9 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/cli": "^0.13.2", - "@backstage/types": "^0.1.1", + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/cli": "^0.14.0", + "@backstage/types": "^0.1.2", "@types/supertest": "^2.0.8", "mock-fs": "^5.1.0", "msw": "^0.35.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index a19153c4e9..fb405a518d 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-auth-backend +## 0.10.2 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/types@0.1.3 + - @backstage/plugin-auth-node@0.1.2 + +## 0.10.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- a31559d1f5: Bump `passport-oauth2` to version 1.6.1 +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 1433045c08: Removed unused `helmet` dependency. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/plugin-auth-node@0.1.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.10.0 ### Minor Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 580d8b8543..3b2946d89a 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.10.0", + "version": "0.10.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,22 +24,22 @@ "backstage" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-auth-node": "^0.1.0", - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/types": "^0.1.1", + "@backstage/plugin-auth-node": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/types": "^0.1.2", "@google-cloud/firestore": "^5.0.2", "@types/express": "^4.17.6", "@types/passport": "^1.0.3", @@ -48,7 +51,6 @@ "express-session": "^1.17.1", "fs-extra": "9.1.0", "google-auth-library": "^7.6.1", - "helmet": "^4.0.0", "jose": "^1.27.1", "jwt-decode": "^3.1.0", "knex": "^1.0.2", @@ -65,7 +67,7 @@ "passport-gitlab2": "^5.0.0", "passport-google-oauth20": "^2.0.0", "passport-microsoft": "^0.1.0", - "passport-oauth2": "^1.5.0", + "passport-oauth2": "^1.6.1", "passport-okta-oauth": "^0.0.1", "passport-onelogin-oauth": "^0.0.1", "passport-saml": "^3.1.2", @@ -74,8 +76,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts index 897233294f..4388c2f82f 100644 --- a/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts +++ b/plugins/auth-backend/src/lib/catalog/CatalogIdentityClient.test.ts @@ -30,11 +30,11 @@ describe('CatalogIdentityClient', () => { getEntities: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const tokenManager: jest.Mocked = { getToken: jest.fn(), diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index 75a3605483..07611ddb9c 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -18,7 +18,7 @@ import express, { CookieOptions } from 'express'; import crypto from 'crypto'; import { URL } from 'url'; import { - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, parseEntityRef, stringifyEntityRef, } from '@backstage/catalog-model'; @@ -271,7 +271,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { const userEntityRef = stringifyEntityRef( parseEntityRef(identity.id, { defaultKind: 'user', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }), ); const token = await this.options.tokenIssuer.issueToken({ diff --git a/plugins/auth-backend/src/providers/github/provider.ts b/plugins/auth-backend/src/providers/github/provider.ts index ec7f8cafa6..29e8679fe0 100644 --- a/plugins/auth-backend/src/providers/github/provider.ts +++ b/plugins/auth-backend/src/providers/github/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import { Logger } from 'winston'; import { Profile as PassportProfile } from 'passport'; @@ -247,10 +251,16 @@ export const githubDefaultSignInResolver: SignInResolver< const userId = fullProfile.username || fullProfile.id; + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ claims: { - sub: `user:default/${userId}`, - ent: [`user:default/${userId}`], + sub: entityRef, + ent: [entityRef], }, }); diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index 6689aba884..59f9a5a4cb 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -14,10 +14,13 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import { Strategy as GitlabStrategy } from 'passport-gitlab2'; import { Logger } from 'winston'; - import { executeRedirectStrategy, executeFrameHandlerStrategy, @@ -71,8 +74,17 @@ export const gitlabDefaultSignInResolver: SignInResolver = async ( id = profile.email.split('@')[0]; } + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: id, + }); + const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: `user:default/${id}`, ent: [`user:default/${id}`] }, + claims: { + sub: entityRef, + ent: [entityRef], + }, }); return { id, token }; diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index fbaf8c7462..e5e5698ec4 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import passport from 'passport'; import { Strategy as GoogleStrategy } from 'passport-google-oauth20'; @@ -226,8 +230,17 @@ const googleDefaultSignInResolver: SignInResolver = async ( userId = profile.email.split('@')[0]; } + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: `user:default/${userId}`, ent: [`user:default/${userId}`] }, + claims: { + sub: entityRef, + ent: [entityRef], + }, }); return { id: userId, token }; diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 25c940547b..98f94811bd 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import passport from 'passport'; import { Strategy as MicrosoftStrategy } from 'passport-microsoft'; @@ -231,10 +235,16 @@ export const microsoftDefaultSignInResolver: SignInResolver< const userId = profile.email.split('@')[0]; + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ claims: { - sub: `user:default/${userId}`, - ent: [`user:default/${userId}`], + sub: entityRef, + ent: [entityRef], }, }); diff --git a/plugins/auth-backend/src/providers/oauth2/index.ts b/plugins/auth-backend/src/providers/oauth2/index.ts index 767466f8f6..d68208a148 100644 --- a/plugins/auth-backend/src/providers/oauth2/index.ts +++ b/plugins/auth-backend/src/providers/oauth2/index.ts @@ -15,5 +15,4 @@ */ export { createOAuth2Provider } from './provider'; - export type { OAuth2ProviderOptions } from './provider'; diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index 0906005791..d09337f5ad 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import passport from 'passport'; import { Strategy as OAuth2Strategy } from 'passport-oauth2'; @@ -210,8 +214,17 @@ export const oAuth2DefaultSignInResolver: SignInResolver = async ( const userId = profile.email.split('@')[0]; + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: `user:default/${userId}`, ent: [`user:default/${userId}`] }, + claims: { + sub: entityRef, + ent: [entityRef], + }, }); return { id: userId, token }; diff --git a/plugins/auth-backend/src/providers/oidc/index.ts b/plugins/auth-backend/src/providers/oidc/index.ts index 39bd02928d..e63c9920df 100644 --- a/plugins/auth-backend/src/providers/oidc/index.ts +++ b/plugins/auth-backend/src/providers/oidc/index.ts @@ -13,5 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export type { OidcAuthResult, OidcProviderOptions } from './provider'; export { createOidcProvider } from './provider'; diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index 9ccdf25f74..b4f34cd127 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import { Client, @@ -211,21 +215,31 @@ export class OidcAuthProvider implements OAuthHandlers { } } -export const oAuth2DefaultSignInResolver: SignInResolver< - OidcAuthResult -> = async (info, ctx) => { +export const oidcDefaultSignInResolver: SignInResolver = async ( + info, + ctx, +) => { const { profile } = info; if (!profile.email) { throw new Error('Profile contained no email'); } + const userId = profile.email.split('@')[0]; + + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ claims: { - sub: `user:default/${userId}`, - ent: [`user:default/${userId}`], + sub: entityRef, + ent: [entityRef], }, }); + return { id: userId, token }; }; @@ -289,7 +303,7 @@ export const createOidcProvider = ( }, }); const signInResolverFn = - options?.signIn?.resolver ?? oAuth2DefaultSignInResolver; + options?.signIn?.resolver ?? oidcDefaultSignInResolver; const signInResolver: SignInResolver = info => signInResolverFn(info, { catalogIdentityClient, diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 0ba7d241d3..26f586c578 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -13,6 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import { OAuthAdapter, @@ -235,8 +240,17 @@ export const oktaDefaultSignInResolver: SignInResolver = async ( // TODO(Rugvip): Hardcoded to the local part of the email for now const userId = profile.email.split('@')[0]; + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: userId, + }); + const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: `user:default/${userId}`, ent: [`user:default/${userId}`] }, + claims: { + sub: entityRef, + ent: [entityRef], + }, }); return { id: userId, token }; diff --git a/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts b/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts index f3b234c08e..5a4e0895d9 100644 --- a/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts +++ b/plugins/auth-backend/src/providers/prepareBackstageIdentityResponse.ts @@ -15,7 +15,7 @@ */ import { - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, parseEntityRef, stringifyEntityRef, } from '@backstage/catalog-model'; @@ -44,7 +44,7 @@ export function prepareBackstageIdentityResponse( const userEntityRef = stringifyEntityRef( parseEntityRef(sub, { defaultKind: 'user', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }), ); return { diff --git a/plugins/auth-backend/src/providers/saml/provider.ts b/plugins/auth-backend/src/providers/saml/provider.ts index 1ca8cf0d5d..4458d423ef 100644 --- a/plugins/auth-backend/src/providers/saml/provider.ts +++ b/plugins/auth-backend/src/providers/saml/provider.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; import express from 'express'; import { SamlConfig } from 'passport-saml/lib/passport-saml/types'; import { @@ -150,8 +154,17 @@ const samlDefaultSignInResolver: SignInResolver = async ( ) => { const id = info.result.fullProfile.nameID; + const entityRef = stringifyEntityRef({ + kind: 'User', + namespace: DEFAULT_NAMESPACE, + name: id, + }); + const token = await ctx.tokenIssuer.issueToken({ - claims: { sub: id }, + claims: { + sub: entityRef, + ent: [entityRef], + }, }); return { id, token }; diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index a5103ea034..fbae9b236c 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-auth-node +## 0.1.2 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + +## 0.1.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.1.0 ### Minor Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 4e059c5e19..435ff21fed 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.1.0", + "version": "0.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,25 +10,29 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "scripts": { - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", "jose": "^1.27.1", "node-fetch": "^2.6.7", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "msw": "^0.35.0", "uuid": "^8.0.0" }, diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 0b44be4e13..c954dd95d9 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-azure-devops-backend +## 0.3.5 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/plugin-azure-devops-common@0.2.2 + +## 0.3.4 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 + - @backstage/plugin-azure-devops-common@0.2.1 + ## 0.3.3 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index a87a48046e..a716613c01 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.3", + "version": "0.3.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,19 +10,22 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/plugin-azure-devops-common": "^0.2.0", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/plugin-azure-devops-common": "^0.2.1", "@types/express": "^4.17.6", "azure-devops-node-api": "^11.0.1", "express": "^4.17.1", @@ -32,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", "msw": "^0.35.0" diff --git a/plugins/azure-devops-common/CHANGELOG.md b/plugins/azure-devops-common/CHANGELOG.md index 74129ea19e..65eaa862fb 100644 --- a/plugins/azure-devops-common/CHANGELOG.md +++ b/plugins/azure-devops-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-azure-devops-common +## 0.2.2 + +### Patch Changes + +- Fix for the previous release with missing type declarations. + +## 0.2.1 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` + ## 0.2.0 ### Minor Changes diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index 02faebca61..1e7b0eaa18 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-common", - "version": "0.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,15 +24,15 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test --passWithNoTests", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 8b0331e75d..321c418b42 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-azure-devops +## 0.1.15 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + - @backstage/plugin-azure-devops-common@0.2.1 + ## 0.1.14 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index a34686d856..d72eb4dd23 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -17,23 +20,23 @@ "directory": "plugins/azure-devops" }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-azure-devops-common": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-azure-devops-common": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -46,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index f025515703..ef2a910c48 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-badges-backend +## 0.1.20 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + +## 0.1.19 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.1.18 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index b5fc38f289..635d282039 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.18", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,20 @@ "badges" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", "@types/express": "^4.17.6", "badge-maker": "^3.3.0", "cors": "^2.8.5", @@ -45,7 +48,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges-backend/src/badges.ts b/plugins/badges-backend/src/badges.ts index 9e4087e334..78108de080 100644 --- a/plugins/badges-backend/src/badges.ts +++ b/plugins/badges-backend/src/badges.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; import { Badge, BadgeContext, BadgeFactories } from './types'; @@ -24,9 +24,9 @@ function appTitle(context: BadgeContext): string { function entityUrl(context: BadgeContext): string { const e = context.entity!; - const entityUri = `${e.metadata.namespace || ENTITY_DEFAULT_NAMESPACE}/${ - e.kind - }/${e.metadata.name}`; + const entityUri = `${e.metadata.namespace || DEFAULT_NAMESPACE}/${e.kind}/${ + e.metadata.name + }`; const catalogUrl = `${context.config.getString('app.baseUrl')}/catalog`; return `${catalogUrl}/${entityUri}`.toLowerCase(); } diff --git a/plugins/badges-backend/src/service/router.test.ts b/plugins/badges-backend/src/service/router.test.ts index 286a2335f1..56dbfb0655 100644 --- a/plugins/badges-backend/src/service/router.test.ts +++ b/plugins/badges-backend/src/service/router.test.ts @@ -61,13 +61,13 @@ describe('createRouter', () => { addLocation: jest.fn(), getEntities: jest.fn(), getEntityByName: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; config = new ConfigReader({ diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 8f2a3b2e84..3666b24b9d 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-badges +## 0.2.23 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.22 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 5250318164..f1b515892a 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.22", + "version": "0.2.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -17,22 +20,22 @@ "directory": "plugins/badges" }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +46,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/badges/src/api/BadgesClient.ts b/plugins/badges/src/api/BadgesClient.ts index 68714b2fa4..f63003dc90 100644 --- a/plugins/badges/src/api/BadgesClient.ts +++ b/plugins/badges/src/api/BadgesClient.ts @@ -16,7 +16,7 @@ import { generatePath } from 'react-router'; import { ResponseError } from '@backstage/errors'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { BadgesApi, BadgeSpec } from './types'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; @@ -63,7 +63,7 @@ export class BadgesClient implements BadgesApi { kind: entity.kind.toLocaleLowerCase('en-US'), namespace: entity.metadata.namespace?.toLocaleLowerCase('en-US') ?? - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, name: entity.metadata.name, }; } diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index fdd63ff59b..57e40cb4de 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-bazaar-backend +## 0.1.10 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/backend-test-utils@0.1.18 + - @backstage/config@0.1.14 + ## 0.1.9 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 71980acea4..22d99c651a 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.1.9", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,19 +10,22 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/config": "^0.1.13", + "@backstage/backend-common": "^0.10.8", + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/config": "^0.1.14", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -31,7 +34,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2" + "@backstage/cli": "^0.14.0" }, "files": [ "dist", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index 00f7605888..2ac6eb442d 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bazaar +## 0.1.14 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/cli@0.14.0 + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog@0.8.0 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + ## 0.1.13 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index bfdcb18ca3..1c2d28fb6b 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.13", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,24 +10,27 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/cli": "^0.13.2", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/plugin-catalog-react": "^0.6.14", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/cli": "^0.14.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/plugin-catalog-react": "^0.6.15", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -44,8 +47,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/dev-utils": "^0.2.21", + "@backstage/cli": "^0.14.0", + "@backstage/dev-utils": "^0.2.22", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.1.5" }, diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 3fc26f7da7..ab21adf45f 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-bitrise +## 0.1.26 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.1.25 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 8b50459a84..e59ea09130 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.25", + "version": "0.1.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,22 +10,25 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog-backend-module-aws/.eslintrc.js b/plugins/catalog-backend-module-aws/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/catalog-backend-module-aws/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/catalog-backend-module-aws/README.md b/plugins/catalog-backend-module-aws/README.md new file mode 100644 index 0000000000..304fe7a080 --- /dev/null +++ b/plugins/catalog-backend-module-aws/README.md @@ -0,0 +1,10 @@ +# Catalog Backend Module for LDAP + +This is an extension module to the plugin-catalog-backend plugin, providing an +`AwsOrganizationCloudAccountProcessor` that can be used to ingest cloud accounts +as `Resource` kind entities. + +## Getting started + +See [Backstage documentation](https://backstage.io/docs/integrations/ldap/org) for details on how to install +and configure the plugin. diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md new file mode 100644 index 0000000000..159420f8e9 --- /dev/null +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-aws" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; +import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; +import { Config } from '@backstage/config'; +import { LocationSpec } from '@backstage/catalog-model'; +import { Logger as Logger_2 } from 'winston'; + +// @public +export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { + // (undocumented) + static fromConfig( + config: Config, + options: { + logger: Logger_2; + }, + ): AwsOrganizationCloudAccountProcessor; + // (undocumented) + getProcessorName(): string; + // (undocumented) + readLocation( + location: LocationSpec, + _optional: boolean, + emit: CatalogProcessorEmit, + ): Promise; +} +``` diff --git a/plugins/catalog-backend-module-aws/config.d.ts b/plugins/catalog-backend-module-aws/config.d.ts new file mode 100644 index 0000000000..bb416a576e --- /dev/null +++ b/plugins/catalog-backend-module-aws/config.d.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 interface Config { + catalog?: { + /** + * List of processor-specific options and attributes + */ + processors?: { + /** + * AwsOrganizationCloudAccountProcessor configuration + */ + awsOrganization?: { + provider: { + /** + * The role to be assumed by this processor + */ + roleArn?: string; + }; + }; + }; + }; +} diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json new file mode 100644 index 0000000000..cff50bb55a --- /dev/null +++ b/plugins/catalog-backend-module-aws/package.json @@ -0,0 +1,55 @@ +{ + "name": "@backstage/plugin-catalog-backend-module-aws", + "description": "A Backstage catalog backend module that helps integrate towards AWS", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": false, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/catalog-backend-module-aws" + }, + "keywords": [ + "backstage" + ], + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" + }, + "dependencies": { + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-backend": "^0.21.4", + "@backstage/types": "^0.1.2", + "aws-sdk": "^2.840.0", + "lodash": "^4.17.21", + "winston": "^3.2.1" + }, + "devDependencies": { + "@backstage/cli": "^0.14.0", + "@types/lodash": "^4.14.151", + "aws-sdk-mock": "^5.2.1" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/catalog-backend/src/ingestion/processors/awsOrganization/config.test.ts b/plugins/catalog-backend-module-aws/src/awsOrganization/config.test.ts similarity index 100% rename from plugins/catalog-backend/src/ingestion/processors/awsOrganization/config.test.ts rename to plugins/catalog-backend-module-aws/src/awsOrganization/config.test.ts diff --git a/plugins/catalog-backend/src/ingestion/processors/awsOrganization/config.ts b/plugins/catalog-backend-module-aws/src/awsOrganization/config.ts similarity index 100% rename from plugins/catalog-backend/src/ingestion/processors/awsOrganization/config.ts rename to plugins/catalog-backend-module-aws/src/awsOrganization/config.ts diff --git a/plugins/catalog-backend-module-aws/src/index.ts b/plugins/catalog-backend-module-aws/src/index.ts new file mode 100644 index 0000000000..62c10a0f6d --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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. + */ + +/** + * A Backstage catalog backend module that helps integrate towards AWS + * + * @packageDocumentation + */ + +export * from './processors'; diff --git a/plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.test.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts similarity index 96% rename from plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.test.ts rename to plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts index 88b033c33f..a7da6d9ad3 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.test.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.test.ts @@ -15,13 +15,11 @@ */ import { AwsOrganizationCloudAccountProcessor } from './AwsOrganizationCloudAccountProcessor'; -import * as winston from 'winston'; describe('AwsOrganizationCloudAccountProcessor', () => { describe('readLocation', () => { - const processor = new AwsOrganizationCloudAccountProcessor({ + const processor = new (AwsOrganizationCloudAccountProcessor as any)({ provider: {}, - logger: winston.createLogger(), }); const location = { type: 'aws-cloud-accounts', target: '' }; const emit = jest.fn(); diff --git a/plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts similarity index 82% rename from plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.ts rename to plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts index 655f99d14a..5db39cefaa 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AwsOrganizationCloudAccountProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts @@ -13,35 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { LocationSpec, ResourceEntityV1alpha1 } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + CatalogProcessor, + CatalogProcessorEmit, + results, +} from '@backstage/plugin-catalog-backend'; import AWS, { Credentials, Organizations } from 'aws-sdk'; import { Account, ListAccountsResponse } from 'aws-sdk/clients/organizations'; - -import * as results from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; -import { Config } from '@backstage/config'; import { Logger } from 'winston'; import { AwsOrganizationProviderConfig, readAwsOrganizationConfig, -} from './awsOrganization/config'; +} from '../awsOrganization/config'; const AWS_ORGANIZATION_REGION = 'us-east-1'; const LOCATION_TYPE = 'aws-cloud-accounts'; -const ACCOUNTID_ANNOTATION: string = 'amazonaws.com/account-id'; -const ARN_ANNOTATION: string = 'amazonaws.com/arn'; -const ORGANIZATION_ANNOTATION: string = 'amazonaws.com/organization-id'; +const ACCOUNTID_ANNOTATION = 'amazonaws.com/account-id'; +const ARN_ANNOTATION = 'amazonaws.com/arn'; +const ORGANIZATION_ANNOTATION = 'amazonaws.com/organization-id'; /** * A processor for ingesting AWS Accounts from AWS Organizations. * - * If custom authentication is needed, it can be achieved by configuring the global AWS.credentials object. + * If custom authentication is needed, it can be achieved by configuring the + * global AWS.credentials object. + * + * @public */ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { - logger: Logger; - organizations: Organizations; - provider: AwsOrganizationProviderConfig; + private readonly organizations: Organizations; + private readonly provider: AwsOrganizationProviderConfig; static fromConfig(config: Config, options: { logger: Logger }) { const c = config.getOptionalConfig('catalog.processors.awsOrganization'); @@ -67,12 +72,8 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { }); } - constructor(options: { - provider: AwsOrganizationProviderConfig; - logger: Logger; - }) { + private constructor(options: { provider: AwsOrganizationProviderConfig }) { this.provider = options.provider; - this.logger = options.logger; const credentials = AwsOrganizationCloudAccountProcessor.buildCredentials( this.provider, ); @@ -82,64 +83,8 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { }); // Only available in us-east-1 } - normalizeName(name: string): string { - return name - .trim() - .toLocaleLowerCase() - .replace(/[^a-zA-Z0-9\-]/g, '-'); - } - - extractInformationFromArn(arn: string): { - accountId: string; - organizationId: string; - } { - const parts = arn.split('/'); - - return { - accountId: parts[parts.length - 1], - organizationId: parts[parts.length - 2], - }; - } - - async getAwsAccounts(): Promise { - let awsAccounts: Account[] = []; - let isInitialAttempt = true; - let nextToken = undefined; - while (isInitialAttempt || nextToken) { - isInitialAttempt = false; - const orgAccounts: ListAccountsResponse = await this.organizations - .listAccounts({ NextToken: nextToken }) - .promise(); - if (orgAccounts.Accounts) { - awsAccounts = awsAccounts.concat(orgAccounts.Accounts); - } - nextToken = orgAccounts.NextToken; - } - - return awsAccounts; - } - - mapAccountToComponent(account: Account): ResourceEntityV1alpha1 { - const { accountId, organizationId } = this.extractInformationFromArn( - account.Arn as string, - ); - return { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Resource', - metadata: { - annotations: { - [ACCOUNTID_ANNOTATION]: accountId, - [ARN_ANNOTATION]: account.Arn || '', - [ORGANIZATION_ANNOTATION]: organizationId, - }, - name: this.normalizeName(account.Name || ''), - namespace: 'default', - }, - spec: { - type: 'cloud-account', - owner: 'unknown', - }, - }; + getProcessorName(): string { + return 'AwsOrganizationCloudAccountProcessor'; } async readLocation( @@ -165,10 +110,70 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { } return true; }) - .forEach((entity: ResourceEntityV1alpha1) => { + .forEach(entity => { emit(results.entity(location, entity)); }); return true; } + + private normalizeName(name: string): string { + return name + .trim() + .toLocaleLowerCase('en-US') + .replace(/[^a-zA-Z0-9\-]/g, '-'); + } + + private extractInformationFromArn(arn: string): { + accountId: string; + organizationId: string; + } { + const parts = arn.split('/'); + + return { + accountId: parts[parts.length - 1], + organizationId: parts[parts.length - 2], + }; + } + + private async getAwsAccounts(): Promise { + let awsAccounts: Account[] = []; + let isInitialAttempt = true; + let nextToken = undefined; + while (isInitialAttempt || nextToken) { + isInitialAttempt = false; + const orgAccounts: ListAccountsResponse = await this.organizations + .listAccounts({ NextToken: nextToken }) + .promise(); + if (orgAccounts.Accounts) { + awsAccounts = awsAccounts.concat(orgAccounts.Accounts); + } + nextToken = orgAccounts.NextToken; + } + + return awsAccounts; + } + + private mapAccountToComponent(account: Account): ResourceEntityV1alpha1 { + const { accountId, organizationId } = this.extractInformationFromArn( + account.Arn as string, + ); + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + annotations: { + [ACCOUNTID_ANNOTATION]: accountId, + [ARN_ANNOTATION]: account.Arn || '', + [ORGANIZATION_ANNOTATION]: organizationId, + }, + name: this.normalizeName(account.Name || ''), + namespace: 'default', + }, + spec: { + type: 'cloud-account', + owner: 'unknown', + }, + }; + } } diff --git a/plugins/catalog/src/components/CatalogResultListItem/index.ts b/plugins/catalog-backend-module-aws/src/processors/index.ts similarity index 86% rename from plugins/catalog/src/components/CatalogResultListItem/index.ts rename to plugins/catalog-backend-module-aws/src/processors/index.ts index e8a67d8f89..fa858aa744 100644 --- a/plugins/catalog/src/components/CatalogResultListItem/index.ts +++ b/plugins/catalog-backend-module-aws/src/processors/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { CatalogResultListItem } from './CatalogResultListItem'; +export { AwsOrganizationCloudAccountProcessor } from './AwsOrganizationCloudAccountProcessor'; diff --git a/plugins/catalog-backend-module-aws/src/setupTests.ts b/plugins/catalog-backend-module-aws/src/setupTests.ts new file mode 100644 index 0000000000..d3232290a7 --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * 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 {}; diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 55162c6003..594fb5593b 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.3.13 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 244d24ebc4: Import `Location` from the `@backstage/catalog-client` package. +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/plugin-catalog-backend@0.21.4 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.3.12 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md index e2dbef74e5..e14dc54a6b 100644 --- a/plugins/catalog-backend-module-ldap/api-report.md +++ b/plugins/catalog-backend-module-ldap/api-report.md @@ -137,6 +137,8 @@ export class LdapOrgReaderProcessor implements CatalogProcessor { }, ): LdapOrgReaderProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, diff --git a/plugins/catalog-backend-module-ldap/config.d.ts b/plugins/catalog-backend-module-ldap/config.d.ts index 57781fd711..df167bc520 100644 --- a/plugins/catalog-backend-module-ldap/config.d.ts +++ b/plugins/catalog-backend-module-ldap/config.d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { JsonValue } from '@backstage/config'; +import { JsonValue } from '@backstage/types'; export interface Config { /** diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index a499049265..01a14a1ad0 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", - "description": "A Backstage catalog backend modules that helps integrate towards LDAP", - "version": "0.3.12", + "description": "A Backstage catalog backend module that helps integrate towards LDAP", + "version": "0.3.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,26 +24,27 @@ "backstage" ], "scripts": { - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-backend": "^0.21.3", - "@backstage/types": "^0.1.1", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-backend": "^0.21.4", + "@backstage/types": "^0.1.2", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", "lodash": "^4.17.21", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-ldap/src/index.ts b/plugins/catalog-backend-module-ldap/src/index.ts index a3b3c46815..243044369c 100644 --- a/plugins/catalog-backend-module-ldap/src/index.ts +++ b/plugins/catalog-backend-module-ldap/src/index.ts @@ -15,7 +15,7 @@ */ /** - * A Backstage catalog backend modules that helps integrate towards LDAP + * A Backstage catalog backend module that helps integrate towards LDAP * * @packageDocumentation */ diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts index c74e5b3aee..4c5bd2e3bd 100644 --- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts @@ -15,9 +15,9 @@ */ import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, Entity, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { @@ -207,8 +207,8 @@ function withLocations(providerId: string, entity: Entity): Entity { { metadata: { annotations: { - [LOCATION_ANNOTATION]: location, - [ORIGIN_LOCATION_ANNOTATION]: location, + [ANNOTATION_LOCATION]: location, + [ANNOTATION_ORIGIN_LOCATION]: location, }, }, }, diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts index be2d748840..4d492c2454 100644 --- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts @@ -69,6 +69,10 @@ export class LdapOrgReaderProcessor implements CatalogProcessor { this.userTransformer = options.userTransformer; } + getProcessorName(): string { + return 'LdapOrgReaderProcessor'; + } + async readLocation( location: LocationSpec, _optional: boolean, diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 847fbae9d4..cd6b717254 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.2.16 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/plugin-catalog-backend@0.21.4 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.2.15 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 4f5d247a06..bb442aa544 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -134,6 +134,8 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { }, ): MicrosoftGraphOrgReaderProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 7fd0a2d319..8eff30c3f0 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "description": "A Backstage catalog backend modules that helps integrate towards Microsoft Graph", - "version": "0.2.15", + "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", + "version": "0.2.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,18 +24,19 @@ "backstage" ], "scripts": { - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { "@azure/msal-node": "^1.1.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/plugin-catalog-backend": "^0.21.3", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/plugin-catalog-backend": "^0.21.4", "@microsoft/microsoft-graph-types": "^2.6.0", "@types/node-fetch": "^2.5.12", "lodash": "^4.17.21", @@ -42,9 +46,9 @@ "qs": "^6.9.4" }, "devDependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/backend-common": "^0.10.8", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/lodash": "^4.14.151", "msw": "^0.35.0" }, diff --git a/plugins/catalog-backend-module-msgraph/src/index.ts b/plugins/catalog-backend-module-msgraph/src/index.ts index 396ccc3e6a..6a7adedc58 100644 --- a/plugins/catalog-backend-module-msgraph/src/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/index.ts @@ -15,7 +15,7 @@ */ /** - * A Backstage catalog backend modules that helps integrate towards Microsoft Graph + * A Backstage catalog backend module that helps integrate towards Microsoft Graph * * @packageDocumentation */ diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts index eab2d93526..456afda550 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts @@ -15,9 +15,9 @@ */ import { getVoidLogger } from '@backstage/backend-common'; import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, GroupEntity, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, UserEntity, } from '@backstage/catalog-model'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; @@ -162,8 +162,8 @@ describe('withLocations', () => { name: 'u1', annotations: { [MICROSOFT_GRAPH_USER_ID_ANNOTATION]: 'uid', - [LOCATION_ANNOTATION]: 'msgraph:test/uid', - [ORIGIN_LOCATION_ANNOTATION]: 'msgraph:test/uid', + [ANNOTATION_LOCATION]: 'msgraph:test/uid', + [ANNOTATION_ORIGIN_LOCATION]: 'msgraph:test/uid', }, }, spec: { diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts index 6d66723970..92836893f0 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts @@ -15,9 +15,9 @@ */ import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, Entity, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { @@ -180,8 +180,8 @@ export function withLocations(providerId: string, entity: Entity): Entity { { metadata: { annotations: { - [LOCATION_ANNOTATION]: location, - [ORIGIN_LOCATION_ANNOTATION]: location, + [ANNOTATION_LOCATION]: location, + [ANNOTATION_ORIGIN_LOCATION]: location, }, }, }, diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts index e0e63d86fc..78b2922f60 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts @@ -73,6 +73,9 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { this.groupTransformer = options.groupTransformer; this.organizationTransformer = options.organizationTransformer; } + getProcessorName(): string { + return 'MicrosoftGraphOrgReaderProcessor'; + } async readLocation( location: LocationSpec, diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index a371712c80..5607f08dc9 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,64 @@ # @backstage/plugin-catalog-backend +## 0.21.5 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/search-common@0.2.4 + - @backstage/types@0.1.3 + - @backstage/plugin-catalog-common@0.1.4 + - @backstage/plugin-permission-common@0.5.1 + - @backstage/plugin-permission-node@0.5.1 + - @backstage/plugin-scaffolder-common@0.2.1 + +## 0.21.4 + +### Patch Changes + +- 379da9fb1d: The following processors now properly accept an `ScmIntegrationRegistry` (an + interface) instead of an `ScmIntegrations` (which is a concrete class). + + - `AzureDevOpsDiscoveryProcessor` + - `CodeOwnersProcessor` + - `GitLabDiscoveryProcessor` + - `GithubDiscoveryProcessor` + - `GithubMultiOrgReaderProcessor` + - `GithubOrgReaderProcessor` + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- ca1d6c1788: Support "dependencyOf" relation in Resource entities +- 244d24ebc4: Import `Location` from the `@backstage/catalog-client` package. +- e483dd6c72: Update internal `Location` validation. +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead + of `@backstage/catalog-model`. +- 27eccab216: Replaces use of deprecated catalog-model constants. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- b590e9b58d: Optimized entity provider mutations with large numbers of new additions, such as big initial startup commits +- Updated dependencies + - @backstage/plugin-scaffolder-common@0.2.0 + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + - @backstage/types@0.1.2 + - @backstage/plugin-catalog-common@0.1.3 + - @backstage/plugin-permission-node@0.5.0 + ## 0.21.3 ### Patch Changes @@ -725,16 +784,16 @@ ### Minor Changes -- 8bfc0571c: Add a default catalog value for BitBucketDiscoveryProcessor. This allows to have a target like so: https://bitbucket.mycompany.com/projects/backstage/repos/service-* - which will be expanded to https://bitbucket.mycompany.com/projects/backstage/repos/service-a/catalog-info.yaml given that repository 'service-a' exists. +- 8bfc0571c: Add a default catalog value for BitBucketDiscoveryProcessor. This allows to have a target like so: `https://bitbucket.mycompany.com/projects/backstage/repos/service-*` + which will be expanded to `https://bitbucket.mycompany.com/projects/backstage/repos/service-a/catalog-info.yaml` given that repository 'service-a' exists. ## Migration If you are using a custom [Bitbucket parser](https://backstage.io/docs/integrations/bitbucket/discovery#custom-repository-processing) and your `bitbucket-discovery` target (e.g. in your app-config.yaml) omits the catalog path in any of the following ways: - - https://bitbucket.mycompany.com/projects/backstage/repos/service-* - - https://bitbucket.mycompany.com/projects/backstage/repos/* - - https://bitbucket.mycompany.com/projects/backstage/repos/*/ + - `https://bitbucket.mycompany.com/projects/backstage/repos/service-*` + - `https://bitbucket.mycompany.com/projects/backstage/repos/*` + - `https://bitbucket.mycompany.com/projects/backstage/repos/*/` then you will be affected by this change. The 'target' input to your parser before this commit would be '/', and after this commit it will be '/catalog-info.yaml', and as such needs to be handled to maintain the same functionality. @@ -1052,7 +1111,7 @@ - 0fd4ea443: Updates the `GithubCredentialsProvider` to return the token type, it can either be `token` or `app` depending on the authentication method. - Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4 for more info. + Update the `GithubOrgReaderProcessor` NOT to query for email addresses if GitHub Apps is used for authentication, this is due to inconsistencies in the GitHub API when using server to server communications and installation tokens. See [this community discussion](https://github.community/t/api-v4-unable-to-retrieve-email-resource-not-accessible-by-integration/13831/4) for more info. **Removes** deprecated GithubOrgReaderProcessor provider configuration(`catalog.processors.githubOrg`). If you're using the deprecated config section make sure to migrate to [integrations](https://backstage.io/docs/integrations/github/locations) instead. diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index deed3e2d8b..b2c2dca0bc 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -5,27 +5,25 @@ ```ts /// -import { Account } from 'aws-sdk/clients/organizations'; import { BitbucketIntegration } from '@backstage/integration'; import { CatalogApi } from '@backstage/catalog-client'; -import { CatalogEntitiesRequest } from '@backstage/catalog-client'; import { ConditionalPolicyDecision } from '@backstage/plugin-permission-node'; import { Conditions } from '@backstage/plugin-permission-node'; import { Config } from '@backstage/config'; import { DocumentCollator } from '@backstage/search-common'; import { Entity } from '@backstage/catalog-model'; +import { EntityName } from '@backstage/catalog-model'; import { EntityPolicy } from '@backstage/catalog-model'; -import { EntityRelationSpec } from '@backstage/catalog-model'; import express from 'express'; +import { GetEntitiesRequest } from '@backstage/catalog-client'; import { GithubCredentialsProvider } from '@backstage/integration'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { IndexableDocument } from '@backstage/search-common'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; -import { Location as Location_2 } from '@backstage/catalog-model'; +import { Location as Location_2 } from '@backstage/catalog-client'; import { LocationSpec } from '@backstage/catalog-model'; import { Logger as Logger_2 } from 'winston'; -import { Organizations } from 'aws-sdk'; import { Permission } from '@backstage/plugin-permission-common'; import { PermissionAuthorizer } from '@backstage/plugin-permission-common'; import { PermissionCondition } from '@backstage/plugin-permission-common'; @@ -33,10 +31,8 @@ import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { ResourceEntityV1alpha1 } from '@backstage/catalog-model'; import { Router } from 'express'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { ScmIntegrations } from '@backstage/integration'; import { TokenManager } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Validators } from '@backstage/catalog-model'; @@ -93,6 +89,8 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor { // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts constructor(options: Options); // (undocumented) + getProcessorName(): string; + // (undocumented) preProcessEntity( entity: Entity, location: LocationSpec, @@ -109,62 +107,19 @@ export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { // (undocumented) static fromConfig(config: Config): AnnotateScmSlugEntityProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) preProcessEntity(entity: Entity, location: LocationSpec): Promise; } -// Warning: (ae-missing-release-tag) "AwsOrganizationCloudAccountProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor { - constructor(options: { - provider: AwsOrganizationProviderConfig; - logger: Logger_2; - }); - // (undocumented) - extractInformationFromArn(arn: string): { - accountId: string; - organizationId: string; - }; - // (undocumented) - static fromConfig( - config: Config, - options: { - logger: Logger_2; - }, - ): AwsOrganizationCloudAccountProcessor; - // (undocumented) - getAwsAccounts(): Promise; - // (undocumented) - logger: Logger_2; - // (undocumented) - mapAccountToComponent(account: Account): ResourceEntityV1alpha1; - // (undocumented) - normalizeName(name: string): string; - // (undocumented) - organizations: Organizations; - // (undocumented) - provider: AwsOrganizationProviderConfig; - // (undocumented) - readLocation( - location: LocationSpec, - _optional: boolean, - emit: CatalogProcessorEmit, - ): Promise; -} - -// Warning: (ae-missing-release-tag) "AwsOrganizationProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export type AwsOrganizationProviderConfig = { - roleArn?: string; -}; - // Warning: (ae-missing-release-tag) "AwsS3DiscoveryProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export class AwsS3DiscoveryProcessor implements CatalogProcessor { constructor(reader: UrlReader); // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, optional: boolean, @@ -177,7 +132,10 @@ export class AwsS3DiscoveryProcessor implements CatalogProcessor { // // @public export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { - constructor(options: { integrations: ScmIntegrations; logger: Logger_2 }); + constructor(options: { + integrations: ScmIntegrationRegistry; + logger: Logger_2; + }); // (undocumented) static fromConfig( config: Config, @@ -186,6 +144,8 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { }, ): AzureDevOpsDiscoveryProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -211,6 +171,8 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { }, ): BitbucketDiscoveryProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -231,6 +193,8 @@ export type BitbucketRepositoryParser = (options: { // // @public (undocumented) export class BuiltinKindsEntityProcessor implements CatalogProcessor { + // (undocumented) + getProcessorName(): string; // (undocumented) postProcessEntity( entity: Entity, @@ -350,7 +314,7 @@ export interface CatalogProcessingOrchestrator { // // @public (undocumented) export type CatalogProcessor = { - getProcessorName?(): string; + getProcessorName(): string; readLocation?( location: LocationSpec, optional: boolean, @@ -414,7 +378,7 @@ export type CatalogProcessorErrorResult = { export type CatalogProcessorLocationResult = { type: 'location'; location: LocationSpec; - optional: boolean; + optional?: boolean; }; // Warning: (ae-missing-release-tag) "CatalogProcessorParser" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -464,7 +428,7 @@ export type CatalogRulesEnforcer = { // @public (undocumented) export class CodeOwnersProcessor implements CatalogProcessor { constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger_2; reader: UrlReader; }); @@ -477,6 +441,8 @@ export class CodeOwnersProcessor implements CatalogProcessor { }, ): CodeOwnersProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) preProcessEntity(entity: Entity, location: LocationSpec): Promise; } @@ -509,7 +475,7 @@ export class DefaultCatalogCollator implements DocumentCollator { discovery: PluginEndpointDiscovery; tokenManager: TokenManager; locationTemplate?: string; - filter?: CatalogEntitiesRequest['filter']; + filter?: GetEntitiesRequest['filter']; catalogClient?: CatalogApi; }); // (undocumented) @@ -524,14 +490,14 @@ export class DefaultCatalogCollator implements DocumentCollator { // (undocumented) execute(): Promise; // (undocumented) - protected filter?: CatalogEntitiesRequest['filter']; + protected filter?: GetEntitiesRequest['filter']; // (undocumented) static fromConfig( _config: Config, options: { discovery: PluginEndpointDiscovery; tokenManager: TokenManager; - filter?: CatalogEntitiesRequest['filter']; + filter?: GetEntitiesRequest['filter']; }, ): DefaultCatalogCollator; // (undocumented) @@ -578,11 +544,6 @@ export type DeferredEntity = { locationKey?: string; }; -// Warning: (ae-missing-release-tag) "durationText" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export function durationText(startTimestamp: [number, number]): string; - // @public (undocumented) export type EntitiesCatalog = { entities(request?: EntitiesRequest): Promise; @@ -598,6 +559,7 @@ export type EntitiesCatalog = { authorizationToken?: string; }, ): Promise; + facets(request: EntityFacetsRequest): Promise; }; // Warning: (ae-missing-release-tag) "EntitiesRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -643,6 +605,24 @@ export type EntityAncestryResponse = { }>; }; +// @public +export interface EntityFacetsRequest { + authorizationToken?: string; + facets: string[]; + filter?: EntityFilter; +} + +// @public +export interface EntityFacetsResponse { + facets: Record< + string, + Array<{ + value: string; + count: number; + }> + >; +} + // Warning: (ae-missing-release-tag) "EntityFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -724,10 +704,19 @@ export type EntityProviderMutation = removed: DeferredEntity[]; }; +// @public +export type EntityRelationSpec = { + source: EntityName; + type: string; + target: EntityName; +}; + // Warning: (ae-missing-release-tag) "FileReaderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export class FileReaderProcessor implements CatalogProcessor { + // (undocumented) + getProcessorName(): string; // (undocumented) readLocation( location: LocationSpec, @@ -750,7 +739,7 @@ function generalError( // @public export class GithubDiscoveryProcessor implements CatalogProcessor { constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger_2; githubCredentialsProvider?: GithubCredentialsProvider; }); @@ -763,6 +752,8 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { }, ): GithubDiscoveryProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -773,7 +764,7 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { // @alpha export class GithubMultiOrgReaderProcessor implements CatalogProcessor { constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger_2; orgs: GithubMultiOrgConfig; githubCredentialsProvider?: GithubCredentialsProvider; @@ -787,6 +778,8 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { }, ): GithubMultiOrgReaderProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -828,7 +821,7 @@ export class GitHubOrgEntityProvider implements EntityProvider { // @public export class GithubOrgReaderProcessor implements CatalogProcessor { constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger_2; githubCredentialsProvider?: GithubCredentialsProvider; }); @@ -841,6 +834,8 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { }, ): GithubOrgReaderProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -860,13 +855,13 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { }, ): GitLabDiscoveryProcessor; // (undocumented) + getProcessorName(): string; + // (undocumented) readLocation( location: LocationSpec, _optional: boolean, emit: CatalogProcessorEmit, ): Promise; - // (undocumented) - updateLastActivity(): Promise; } // Warning: (ae-missing-release-tag) "inputError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -882,7 +877,7 @@ function inputError( // @public (undocumented) function location_2( newLocation: LocationSpec, - optional: boolean, + optional?: boolean, ): CatalogProcessorResult; // Warning: (ae-missing-release-tag) "LocationAnalyzer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -900,6 +895,8 @@ export type LocationAnalyzer = { export class LocationEntityProcessor implements CatalogProcessor { constructor(options: LocationEntityProcessorOptions); // (undocumented) + getProcessorName(): string; + // (undocumented) postProcessEntity( entity: Entity, location: LocationSpec, @@ -1024,6 +1021,8 @@ export const permissionRules: { export class PlaceholderProcessor implements CatalogProcessor { constructor(options: PlaceholderProcessorOptions); // (undocumented) + getProcessorName(): string; + // (undocumented) preProcessEntity(entity: Entity, location: LocationSpec): Promise; } @@ -1131,12 +1130,12 @@ export interface RouterOptions { // Warning: (ae-missing-release-tag) "runPeriodically" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public +// @public @deprecated export function runPeriodically(fn: () => any, delayMs: number): () => void; // Warning: (ae-missing-release-tag) "StaticLocationProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // -// @public (undocumented) +// @public @deprecated (undocumented) export class StaticLocationProcessor implements StaticLocationProcessor { constructor(staticLocations: LocationSpec[]); // (undocumented) diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 5701c9df48..8964e1ab0e 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import { JsonValue } from '@backstage/config'; - export interface Config { /** * Configuration options for the catalog plugin. @@ -172,19 +170,6 @@ export interface Config { userNamespace?: string; }>; }; - - /** - * AwsOrganizationCloudAccountProcessor configuration - */ - awsOrganization?: { - provider: { - /** - * The role to be assumed by this processor - * - */ - roleArn?: string; - }; - }; }; }; } diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 40d514bb2f..eb6b185861 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "0.21.3", + "version": "0.21.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,26 +24,27 @@ "backstage" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.3", - "@backstage/search-common": "^0.2.2", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-node": "^0.5.0", + "@backstage/plugin-scaffolder-common": "^0.2.0", + "@backstage/search-common": "^0.2.3", + "@backstage/types": "^0.1.2", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", "aws-sdk": "^2.840.0", @@ -62,19 +66,18 @@ "winston": "^3.2.1", "yaml": "^1.9.2", "yn": "^4.0.0", - "yup": "^0.32.9" + "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/cli": "^0.13.2", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/test-utils": "^0.2.4", + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/cli": "^0.14.0", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/test-utils": "^0.2.5", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", - "@types/yup": "^0.29.13", "@vscode/sqlite3": "^5.0.7", "aws-sdk-mock": "^5.2.1", "msw": "^0.35.0", diff --git a/plugins/catalog-backend/src/catalog/index.ts b/plugins/catalog-backend/src/catalog/index.ts index 95c6572b10..59f67b2f52 100644 --- a/plugins/catalog-backend/src/catalog/index.ts +++ b/plugins/catalog-backend/src/catalog/index.ts @@ -18,9 +18,11 @@ export type { EntitiesCatalog, EntitiesRequest, EntitiesResponse, - EntityAncestryResponse, - PageInfo, EntitiesSearchFilter, + EntityAncestryResponse, + EntityFacetsRequest, + EntityFacetsResponse, EntityFilter, EntityPagination, + PageInfo, } from './types'; diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index a79229b9a1..e285d4c100 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -87,6 +87,44 @@ export type EntityAncestryResponse = { }>; }; +/** + * The request shape for {@link EntitiesCatalog.facets}. + * + * @public + */ +export interface EntityFacetsRequest { + /** + * A filter to apply on the full list of entities before computing the facets. + */ + filter?: EntityFilter; + /** + * The facets to compute. + * + * @remarks + * + * This is a list of strings corresponding to paths within individual entity + * shapes. For example, to compute the facets for all available tags, you + * would pass in the string 'metadata.tags'. + */ + facets: string[]; + /** + * The optional token that authorizes the action. + */ + authorizationToken?: string; +} + +/** + * The response shape for {@link EntitiesCatalog.facets}. + * + * @public + */ +export interface EntityFacetsResponse { + /** + * The computed facets, one entry per facet in the request. + */ + facets: Record>; +} + /** @public */ export type EntitiesCatalog = { /** @@ -115,4 +153,12 @@ export type EntitiesCatalog = { entityRef: string, options?: { authorizationToken?: string }, ): Promise; + + /** + * Computes facets for a set of entities, e.g. for populating filter lists + * or driving insights or similar. + * + * @param request - Request options + */ + facets(request: EntityFacetsRequest): Promise; }; diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts index 905339af17..729be442aa 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts @@ -832,7 +832,7 @@ describe('Default Processing Database', () => { /* config-1 -> location:default/root config-2 -> location:default/root - */ + */ await createLocations(knex, ['location:default/root']); await insertRefRow(knex, { @@ -1092,6 +1092,61 @@ describe('Default Processing Database', () => { }, 60_000, ); + + it.each(databases.eachSupportedId())( + 'should successfully fall back from batch to individual mode on conflicts, %p', + async databaseId => { + const fakeLogger = { + debug: jest.fn(), + }; + const { knex, db } = await createDatabase( + databaseId, + fakeLogger as any, + ); + + await createLocations(knex, ['component:default/a']); + + await insertRefRow(knex, { + source_key: undefined, + target_entity_ref: 'component:default/a', + }); + + await db.transaction(async tx => { + await db.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'lols', + items: [ + { + entity: { + apiVersion: '1', + kind: 'Component', + metadata: { name: 'a' }, + spec: { marker: 'WILL_CHANGE' }, + } as Entity, + locationKey: 'file:///tmp/a', + }, + ], + }); + }); + expect(fakeLogger.debug).toBeCalledWith( + expect.stringMatching( + /Fast insert path failed, falling back to slow path/, + ), + ); + + const state = await knex('refresh_state').select(); + expect(state).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + entity_ref: 'component:default/a', + location_key: 'file:///tmp/a', + unprocessed_entity: expect.stringContaining('WILL_CHANGE'), + }), + ]), + ); + }, + 60_000, + ); }); describe('getProcessableEntities', () => { diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index f2f478c481..55f04c289c 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -45,6 +45,7 @@ import { } from './tables'; import { generateStableHash } from './util'; +import { isDatabaseConflictError } from '@backstage/backend-common'; // The number of items that are sent per batch to the database layer, when // doing .batchInsert calls to knex. This needs to be low enough to not cause @@ -160,7 +161,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ): Promise { const tx = txOpaque as Knex.Transaction; - const { toUpsert, toRemove } = await this.createDelta(tx, options); + const { toAdd, toUpsert, toRemove } = await this.createDelta(tx, options); if (toRemove.length) { // TODO(freben): Batch split, to not hit variable limits? @@ -277,6 +278,53 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } + if (toAdd.length) { + // The reason for this chunking, rather than just massively batch + // inserting the entire payload, is that we fall back to the individual + // upsert mechanism below on conflicts. That path is massively slower than + // the fast batch path, so we don't want to end up accidentally having to + // for example item-by-item upsert tens of thousands of entities in a + // large initial delivery dump. The implication is that the size of these + // chunks needs to weigh the benefit of fast successful inserts, against + // the drawback of super slow but more rare fallbacks. There's quickly + // diminishing returns though with turning up this value way high. + for (const chunk of lodash.chunk(toAdd, 50)) { + try { + await tx.batchInsert( + 'refresh_state', + chunk.map(item => ({ + entity_id: uuid(), + entity_ref: stringifyEntityRef(item.deferred.entity), + unprocessed_entity: JSON.stringify(item.deferred.entity), + unprocessed_hash: item.hash, + errors: '', + location_key: item.deferred.locationKey, + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + })), + BATCH_SIZE, + ); + await tx.batchInsert( + 'refresh_state_references', + chunk.map(item => ({ + source_key: options.sourceKey, + target_entity_ref: stringifyEntityRef(item.deferred.entity), + })), + BATCH_SIZE, + ); + } catch (error) { + if (!isDatabaseConflictError(error)) { + throw error; + } else { + this.options.logger.debug( + `Fast insert path failed, falling back to slow path, ${error}`, + ); + toUpsert.push(...chunk); + } + } + } + } + if (toUpsert.length) { for (const { deferred: { entity, locationKey }, @@ -600,11 +648,13 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { tx: Knex.Transaction, options: ReplaceUnprocessedEntitiesOptions, ): Promise<{ + toAdd: { deferred: DeferredEntity; hash: string }[]; toUpsert: { deferred: DeferredEntity; hash: string }[]; toRemove: string[]; }> { if (options.type === 'delta') { return { + toAdd: [], toUpsert: options.added.map(e => ({ deferred: e, hash: generateStableHash(e.entity), @@ -644,6 +694,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); const newRefsSet = new Set(items.map(item => item.ref)); + const toAdd = new Array<{ deferred: DeferredEntity; hash: string }>(); const toUpsert = new Array<{ deferred: DeferredEntity; hash: string }>(); const toRemove = oldRefs .map(row => row.target_entity_ref) @@ -654,18 +705,18 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { const upsertItem = { deferred: item.deferred, hash: item.hash }; if (!oldRef) { // Add any entity that does not exist in the database - toUpsert.push(upsertItem); + toAdd.push(upsertItem); } else if (oldRef.locationKey !== item.deferred.locationKey) { // Remove and then re-add any entity that exists, but with a different location key toRemove.push(item.ref); - toUpsert.push(upsertItem); + toAdd.push(upsertItem); } else if (oldRef.oldEntityHash !== item.hash) { // Entities with modifications should be pushed through too toUpsert.push(upsertItem); } } - return { toUpsert, toRemove }; + return { toAdd, toUpsert, toRemove }; } /** diff --git a/plugins/catalog-backend/src/database/types.ts b/plugins/catalog-backend/src/database/types.ts index ac2ff07498..08201323ea 100644 --- a/plugins/catalog-backend/src/database/types.ts +++ b/plugins/catalog-backend/src/database/types.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; import { DateTime } from 'luxon'; -import { DeferredEntity } from '../processing/types'; +import { DeferredEntity, EntityRelationSpec } from '../processing/types'; /** * An abstraction for transactions of the underlying database technology. diff --git a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts index 24d6b2fd66..88245d9b81 100644 --- a/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts +++ b/plugins/catalog-backend/src/ingestion/CatalogRules.test.ts @@ -35,11 +35,11 @@ const entity = { const location: Record = { x: { - type: 'github', + type: 'url', target: 'https://github.com/a/b/blob/master/x.yaml', }, y: { - type: 'github', + type: 'url', target: 'https://github.com/a/b/blob/master/y.yaml', }, z: { @@ -180,7 +180,7 @@ describe('DefaultCatalogRulesEnforcer', () => { rules: [{ allow: ['user'] }], locations: [ { - type: 'github', + type: 'url', target: 'https://github.com/a/b/blob/master/x.yaml', rules: [ { @@ -204,7 +204,7 @@ describe('DefaultCatalogRulesEnforcer', () => { const enforcer = DefaultCatalogRulesEnforcer.fromConfig( new ConfigReader({ catalog: { - rules: [{ allow: ['Group'], locations: [{ type: 'github' }] }], + rules: [{ allow: ['Group'], locations: [{ type: 'url' }] }], }, }), ); diff --git a/plugins/catalog-backend/src/ingestion/processors/AnnotateLocationEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AnnotateLocationEntityProcessor.ts index 54079e13ff..90b3280ab8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AnnotateLocationEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AnnotateLocationEntityProcessor.ts @@ -15,14 +15,14 @@ */ import { - EDIT_URL_ANNOTATION, + ANNOTATION_EDIT_URL, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, + ANNOTATION_SOURCE_LOCATION, + ANNOTATION_VIEW_URL, Entity, LocationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, - SOURCE_LOCATION_ANNOTATION, - stringifyLocationReference, - VIEW_URL_ANNOTATION, + stringifyLocationRef, } from '@backstage/catalog-model'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { identity, merge, pickBy } from 'lodash'; @@ -35,6 +35,10 @@ type Options = { export class AnnotateLocationEntityProcessor implements CatalogProcessor { constructor(private readonly options: Options) {} + getProcessorName(): string { + return 'AnnotateLocationEntityProcessor'; + } + async preProcessEntity( entity: Entity, location: LocationSpec, @@ -58,7 +62,7 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor { }); if (sourceUrl) { - sourceLocation = stringifyLocationReference({ + sourceLocation = stringifyLocationRef({ type: 'url', target: sourceUrl, }); @@ -70,12 +74,12 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor { metadata: { annotations: pickBy( { - [LOCATION_ANNOTATION]: stringifyLocationReference(location), - [ORIGIN_LOCATION_ANNOTATION]: - stringifyLocationReference(originLocation), - [VIEW_URL_ANNOTATION]: viewUrl, - [EDIT_URL_ANNOTATION]: editUrl, - [SOURCE_LOCATION_ANNOTATION]: sourceLocation, + [ANNOTATION_LOCATION]: stringifyLocationRef(location), + [ANNOTATION_ORIGIN_LOCATION]: + stringifyLocationRef(originLocation), + [ANNOTATION_VIEW_URL]: viewUrl, + [ANNOTATION_EDIT_URL]: editUrl, + [ANNOTATION_SOURCE_LOCATION]: sourceLocation, }, identity, ), diff --git a/plugins/catalog-backend/src/ingestion/processors/AnnotateScmSlugEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AnnotateScmSlugEntityProcessor.ts index 483472da4b..b3a3cfd999 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AnnotateScmSlugEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AnnotateScmSlugEntityProcessor.ts @@ -30,6 +30,10 @@ export class AnnotateScmSlugEntityProcessor implements CatalogProcessor { private readonly opts: { scmIntegrationRegistry: ScmIntegrationRegistry }, ) {} + getProcessorName(): string { + return 'AnnotateScmSlugEntityProcessor'; + } + static fromConfig(config: Config): AnnotateScmSlugEntityProcessor { return new AnnotateScmSlugEntityProcessor({ scmIntegrationRegistry: ScmIntegrations.fromConfig(config), diff --git a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts index 63bc45726d..77152f81af 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts @@ -28,6 +28,10 @@ import { export class AwsS3DiscoveryProcessor implements CatalogProcessor { constructor(private readonly reader: UrlReader) {} + getProcessorName(): string { + return 'AwsS3DiscoveryProcessor'; + } + async readLocation( location: LocationSpec, optional: boolean, diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts index 463d982ca2..f9913e4f12 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.test.ts @@ -167,7 +167,6 @@ describe('AzureDevOpsDiscoveryProcessor', () => { 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/catalog-info.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -177,7 +176,6 @@ describe('AzureDevOpsDiscoveryProcessor', () => { 'https://dev.azure.com/shopify/engineering/_git/ios-app?path=/src/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); @@ -215,7 +213,6 @@ describe('AzureDevOpsDiscoveryProcessor', () => { 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); @@ -254,7 +251,6 @@ describe('AzureDevOpsDiscoveryProcessor', () => { 'https://dev.azure.com/shopify/engineering/_git/backstage?path=/src/main/catalog.yaml', presence: 'optional', }, - optional: true, }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts index aeac64f54d..c1cc610495 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AzureDevOpsDiscoveryProcessor.ts @@ -16,7 +16,10 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { ScmIntegrations } from '@backstage/integration'; +import { + ScmIntegrationRegistry, + ScmIntegrations, +} from '@backstage/integration'; import { Logger } from 'winston'; import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; @@ -37,7 +40,7 @@ import { codeSearch } from './azure'; * target: https://dev.azure.com/org/project/_git/repo **/ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; static fromConfig(config: Config, options: { logger: Logger }) { @@ -49,11 +52,18 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { }); } - constructor(options: { integrations: ScmIntegrations; logger: Logger }) { + constructor(options: { + integrations: ScmIntegrationRegistry; + logger: Logger; + }) { this.integrations = options.integrations; this.logger = options.logger; } + getProcessorName(): string { + return 'AzureDevOpsDiscoveryProcessor'; + } + async readLocation( location: LocationSpec, _optional: boolean, @@ -91,17 +101,14 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { for (const file of files) { emit( - results.location( - { - type: 'url', - target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`, - presence: 'optional', - }, + results.location({ + type: 'url', + target: `${baseUrl}/${org}/${project}/_git/${file.repository.name}?path=${file.path}`, // Not all locations may actually exist, since the user defined them as a wildcard pattern. // Thus, we emit them as optional and let the downstream processor find them while not outputting // an error if it couldn't. - true, - ), + presence: 'optional', + }), ); } diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts index 7ace995fda..96906dac85 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.test.ts @@ -210,7 +210,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/backstage/repos/backstage/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -220,7 +219,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -246,7 +244,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -269,7 +266,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/demo/repos/demo/browse/catalog.yaml?ref=branch-name', presence: 'optional', }, - optional: true, }); }); @@ -292,7 +288,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/backstage/repos/test/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -321,7 +316,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/projects/backstage/repos/techdocs-cli/browse/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); }); @@ -369,7 +363,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/backstage/repos/backstage/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -379,7 +372,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/demo/repos/demo/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -408,7 +400,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/backstage/repos/techdocs-cli/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -434,7 +425,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/demo/repos/demo/browse/catalog.yaml?ref=branch-name', presence: 'optional', }, - optional: true, }); }); @@ -460,7 +450,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/backstage/repos/test/browse/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -492,7 +481,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.mycompany.com/custom-path/projects/backstage/repos/techdocs-cli/browse/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); }); @@ -536,7 +524,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -546,7 +533,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-two/src/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); @@ -574,7 +560,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/my/nested/path/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -584,7 +569,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-two/src/master/my/nested/path/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -612,7 +596,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -622,7 +605,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-two/src/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -649,7 +631,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -677,7 +658,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-three/src/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -703,7 +683,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }); expect(mockCall).toBeCalledTimes(1); // it should be possible to do this via an `expect.objectContaining` check but seems to fail with some encoding issue. @@ -739,7 +718,6 @@ describe('BitbucketDiscoveryProcessor', () => { 'https://bitbucket.org/myworkspace/repository-one/src/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); @@ -766,13 +744,11 @@ describe('BitbucketDiscoveryProcessor', () => { describe('Custom repository parser', () => { const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({}) { - yield results.location( - { - type: 'custom-location-type', - target: 'custom-target', - }, - true, - ); + yield results.location({ + type: 'custom-location-type', + target: 'custom-target', + presence: 'optional', + }); }; const processor = BitbucketDiscoveryProcessor.fromConfig( @@ -808,8 +784,8 @@ describe('BitbucketDiscoveryProcessor', () => { location: { type: 'custom-location-type', target: 'custom-target', + presence: 'optional', }, - optional: true, }); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts index f08888d1ab..2cc6822eaa 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BitbucketDiscoveryProcessor.ts @@ -64,6 +64,10 @@ export class BitbucketDiscoveryProcessor implements CatalogProcessor { this.logger = options.logger; } + getProcessorName(): string { + return 'BitbucketDiscoveryProcessor'; + } + async readLocation( location: LocationSpec, _optional: boolean, diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index c42980d97b..1b7739a772 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -21,9 +21,9 @@ import { GroupEntity, ResourceEntity, SystemEntity, - TemplateEntityV1beta2, UserEntity, } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor'; describe('BuiltinKindsEntityProcessor', () => { diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index 5999be9793..729cd023f8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -46,11 +46,13 @@ import { resourceEntityV1alpha1Validator, SystemEntity, systemEntityV1alpha1Validator, - TemplateEntityV1beta2, - templateEntityV1beta2Validator, UserEntity, userEntityV1alpha1Validator, } from '@backstage/catalog-model'; +import { + TemplateEntityV1beta2, + templateEntityV1beta2Validator, +} from '@backstage/plugin-scaffolder-common'; import * as result from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; @@ -67,6 +69,10 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { domainEntityV1alpha1Validator, ]; + getProcessorName(): string { + return 'BuiltinKindsEntityProcessor'; + } + async validateEntityKind(entity: Entity): Promise { for (const validator of this.validators) { const results = await validator.check(entity); diff --git a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts index 2f52a1ddd9..3d7d6fde84 100644 --- a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.test.ts @@ -27,7 +27,7 @@ const mockCodeOwnersText = () => ` describe('CodeOwnersProcessor', () => { const mockLocation = ({ basePath = '', - type = 'github', + type = 'url', } = {}): LocationSpec => ({ type, target: `https://github.com/backstage/backstage/blob/master/${basePath}catalog-info.yaml`, diff --git a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts index a70aa6d1a9..ff5dedcbbf 100644 --- a/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/CodeOwnersProcessor.ts @@ -17,25 +17,20 @@ import { UrlReader } from '@backstage/backend-common'; import { Entity, LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { ScmIntegrations } from '@backstage/integration'; +import { + ScmIntegrationRegistry, + ScmIntegrations, +} from '@backstage/integration'; import { Logger } from 'winston'; import { findCodeOwnerByTarget } from './codeowners'; import { CatalogProcessor } from './types'; const ALLOWED_KINDS = ['API', 'Component', 'Domain', 'Resource', 'System']; -const ALLOWED_LOCATION_TYPES = [ - 'url', - 'azure/api', - 'bitbucket/api', - 'github', - 'github/api', - 'gitlab', - 'gitlab/api', -]; +const ALLOWED_LOCATION_TYPES = ['url']; export class CodeOwnersProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; private readonly reader: UrlReader; @@ -52,7 +47,7 @@ export class CodeOwnersProcessor implements CatalogProcessor { } constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger; reader: UrlReader; }) { @@ -61,6 +56,10 @@ export class CodeOwnersProcessor implements CatalogProcessor { this.reader = options.reader; } + getProcessorName(): string { + return 'CodeOwnersProcessor'; + } + async preProcessEntity( entity: Entity, location: LocationSpec, diff --git a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts index 9ff3f52ba0..20020fcfbe 100644 --- a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts @@ -29,6 +29,10 @@ import { const glob = promisify(g); export class FileReaderProcessor implements CatalogProcessor { + getProcessorName(): string { + return 'FileReaderProcessor'; + } + async readLocation( location: LocationSpec, optional: boolean, diff --git a/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.test.ts index 8d85d7375f..8f1da52413 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.test.ts @@ -210,7 +210,6 @@ describe('GitlabDiscoveryProcessor', () => { target: 'https://gitlab.fake/1/-/blob/main/catalog-info.yaml', presence: 'optional', }, - optional: true, }, { type: 'location', @@ -219,7 +218,6 @@ describe('GitlabDiscoveryProcessor', () => { target: 'https://gitlab.fake/2/-/blob/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }, ]); }); @@ -257,7 +255,6 @@ describe('GitlabDiscoveryProcessor', () => { target: 'https://gitlab.fake/1/-/blob/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }, ]); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.ts index fabf3a1136..776ec1e7a8 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GitLabDiscoveryProcessor.ts @@ -16,7 +16,10 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { ScmIntegrations } from '@backstage/integration'; +import { + ScmIntegrationRegistry, + ScmIntegrations, +} from '@backstage/integration'; import { Logger } from 'winston'; import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; @@ -31,7 +34,7 @@ import { * Extracts repositories out of an GitLab instance. */ export class GitLabDiscoveryProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; private readonly cache: CacheClient; @@ -48,7 +51,7 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { } private constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; pluginCache: PluginCacheManager; logger: Logger; }) { @@ -57,6 +60,10 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { this.logger = options.logger; } + getProcessorName(): string { + return 'GitLabDiscoveryProcessor'; + } + async readLocation( location: LocationSpec, _optional: boolean, @@ -110,20 +117,17 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { const project_branch = branch === '*' ? project.default_branch : branch; emit( - results.location( - { - type: 'url', - // The format expected by the GitLabUrlReader: - // https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath - // - // This unfortunately will trigger another API call in `getGitLabFileFetchUrl` to get the project ID. - // The alternative is using the `buildRawUrl` function, which does not support subgroups, so providing a raw - // URL here won't work either. - target: `${project.web_url}/-/blob/${project_branch}/${catalogPath}`, - presence: 'optional', - }, - true, - ), + results.location({ + type: 'url', + // The format expected by the GitLabUrlReader: + // https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/filepath + // + // This unfortunately will trigger another API call in `getGitLabFileFetchUrl` to get the project ID. + // The alternative is using the `buildRawUrl` function, which does not support subgroups, so providing a raw + // URL here won't work either. + target: `${project.web_url}/-/blob/${project_branch}/${catalogPath}`, + presence: 'optional', + }), ); } @@ -135,9 +139,10 @@ export class GitLabDiscoveryProcessor implements CatalogProcessor { return true; } - async updateLastActivity(): Promise { - const lastActivity = await this.cache.get('last-activity'); - await this.cache.set('last-activity', new Date().toISOString()); + private async updateLastActivity(): Promise { + const cacheKey = `processors/${this.getProcessorName()}/last-activity`; + const lastActivity = await this.cache.get(cacheKey); + await this.cache.set(cacheKey, new Date().toISOString()); return lastActivity as string | undefined; } } diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts index d6746f13da..1866247212 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.test.ts @@ -175,7 +175,6 @@ describe('GithubDiscoveryProcessor', () => { 'https://github.com/backstage/backstage/blob/master/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -184,7 +183,6 @@ describe('GithubDiscoveryProcessor', () => { target: 'https://github.com/backstage/demo/blob/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -217,7 +215,6 @@ describe('GithubDiscoveryProcessor', () => { 'https://github.com/backstage/tech-docs/blob/main/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -272,7 +269,6 @@ describe('GithubDiscoveryProcessor', () => { 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', presence: 'optional', }, - optional: true, }); }); @@ -328,7 +324,6 @@ describe('GithubDiscoveryProcessor', () => { 'https://github.com/backstage/techdocs-cli/blob/master/catalog.yaml', presence: 'optional', }, - optional: true, }); expect(emitter).toHaveBeenCalledWith({ type: 'location', @@ -338,7 +333,6 @@ describe('GithubDiscoveryProcessor', () => { 'https://github.com/backstage/techdocs-container/blob/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); @@ -394,7 +388,6 @@ describe('GithubDiscoveryProcessor', () => { target: 'https://github.com/backstage/test/blob/master/catalog.yaml', presence: 'optional', }, - optional: true, }); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts index 3196c4e161..ec0de74b00 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubDiscoveryProcessor.ts @@ -19,6 +19,7 @@ import { Config } from '@backstage/config'; import { DefaultGithubCredentialsProvider, GithubCredentialsProvider, + ScmIntegrationRegistry, ScmIntegrations, } from '@backstage/integration'; import { graphql } from '@octokit/graphql'; @@ -42,7 +43,7 @@ import { CatalogProcessor, CatalogProcessorEmit } from './types'; * target: https://github.com/backstage/*\/blob/main/catalog-info.yaml **/ export class GithubDiscoveryProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; private readonly githubCredentialsProvider: GithubCredentialsProvider; @@ -62,7 +63,7 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { } constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger; githubCredentialsProvider?: GithubCredentialsProvider; }) { @@ -72,6 +73,9 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { options.githubCredentialsProvider || DefaultGithubCredentialsProvider.fromIntegrations(this.integrations); } + getProcessorName(): string { + return 'GithubDiscoveryProcessor'; + } async readLocation( location: LocationSpec, @@ -136,17 +140,14 @@ export class GithubDiscoveryProcessor implements CatalogProcessor { const path = `/blob/${branchName}${catalogPath}`; emit( - results.location( - { - type: 'url', - target: `${repository.url}${path}`, - presence: 'optional', - }, + results.location({ + type: 'url', + target: `${repository.url}${path}`, // Not all locations may actually exist, since the user defined them as a wildcard pattern. // Thus, we emit them as optional and let the downstream processor find them while not outputting // an error if it couldn't. - true, - ), + presence: 'optional', + }), ); } diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts index dd705ad691..765b2139fd 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -21,6 +21,7 @@ import { GithubAppCredentialsMux, GithubCredentialsProvider, GitHubIntegrationConfig, + ScmIntegrationRegistry, ScmIntegrations, } from '@backstage/integration'; import { graphql } from '@octokit/graphql'; @@ -42,7 +43,7 @@ import { buildOrgHierarchy } from './util/org'; * Be aware that this processor may not be compatible with future org structures in the catalog. */ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly orgs: GithubMultiOrgConfig; private readonly logger: Logger; private readonly githubCredentialsProvider: GithubCredentialsProvider; @@ -65,7 +66,7 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { } constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger; orgs: GithubMultiOrgConfig; githubCredentialsProvider?: GithubCredentialsProvider; @@ -77,6 +78,9 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { options.githubCredentialsProvider || DefaultGithubCredentialsProvider.fromIntegrations(this.integrations); } + getProcessorName(): string { + return 'GithubMultiOrgReaderProcessor'; + } async readLocation( location: LocationSpec, diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts index 474d08feee..2a411af33e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts @@ -18,6 +18,7 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { GithubCredentialType, + ScmIntegrationRegistry, ScmIntegrations, GithubCredentialsProvider, DefaultGithubCredentialsProvider, @@ -39,7 +40,7 @@ type GraphQL = typeof graphql; * Extracts teams and users out of a GitHub org. */ export class GithubOrgReaderProcessor implements CatalogProcessor { - private readonly integrations: ScmIntegrations; + private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; private readonly githubCredentialsProvider: GithubCredentialsProvider; @@ -59,7 +60,7 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { } constructor(options: { - integrations: ScmIntegrations; + integrations: ScmIntegrationRegistry; logger: Logger; githubCredentialsProvider?: GithubCredentialsProvider; }) { @@ -69,6 +70,9 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { DefaultGithubCredentialsProvider.fromIntegrations(this.integrations); this.logger = options.logger; } + getProcessorName(): string { + return 'GithubOrgReaderProcessor'; + } async readLocation( location: LocationSpec, diff --git a/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts index c6b7def5fc..60941486c3 100644 --- a/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/LocationEntityProcessor.ts @@ -45,6 +45,10 @@ export type LocationEntityProcessorOptions = { export class LocationEntityProcessor implements CatalogProcessor { constructor(private readonly options: LocationEntityProcessorOptions) {} + getProcessorName(): string { + return 'LocationEntityProcessor'; + } + async postProcessEntity( entity: Entity, location: LocationSpec, @@ -77,7 +81,7 @@ export class LocationEntityProcessor implements CatalogProcessor { location, maybeRelativeTarget, ); - emit(result.location({ type, target }, false)); + emit(result.location({ type, target })); } } diff --git a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts index c7a49353ae..7bfc66276e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.test.ts @@ -154,7 +154,7 @@ describe('PlaceholderProcessor', () => { spec: { data: { $text: '../file.txt' } }, }, { - type: 'github', + type: 'url', target: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, @@ -190,7 +190,7 @@ describe('PlaceholderProcessor', () => { spec: { data: { $json: './file.json' } }, }, { - type: 'github', + type: 'url', target: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, @@ -224,7 +224,7 @@ describe('PlaceholderProcessor', () => { spec: { data: { $yaml: '../file.yaml' } }, }, { - type: 'github', + type: 'url', target: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, @@ -262,7 +262,7 @@ describe('PlaceholderProcessor', () => { }, }, { - type: 'github', + type: 'url', target: 'https://github.com/backstage/backstage/a/b/catalog-info.yaml', }, @@ -300,7 +300,7 @@ describe('PlaceholderProcessor', () => { }, }, { - type: 'github', + type: 'url', target: './a/b/catalog-info.yaml', }, ), @@ -340,7 +340,7 @@ describe('PlaceholderProcessor', () => { }, }, { - type: 'github', + type: 'url', target: './a/b/catalog-info.yaml', }, ), diff --git a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.ts index 65f65a0479..1a0ca75ba5 100644 --- a/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/PlaceholderProcessor.ts @@ -52,6 +52,10 @@ export type PlaceholderProcessorOptions = { export class PlaceholderProcessor implements CatalogProcessor { constructor(private readonly options: PlaceholderProcessorOptions) {} + getProcessorName(): string { + return 'PlaceholderProcessor'; + } + async preProcessEntity( entity: Entity, location: LocationSpec, diff --git a/plugins/catalog-backend/src/ingestion/processors/StaticLocationProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/StaticLocationProcessor.ts index 425ad6e0fe..c23c14bac9 100644 --- a/plugins/catalog-backend/src/ingestion/processors/StaticLocationProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/StaticLocationProcessor.ts @@ -19,6 +19,9 @@ import { Config } from '@backstage/config'; import * as result from './results'; import { CatalogProcessorEmit } from './types'; +/** + * @deprecated no longer in use, replaced by the ConfigLocationEntityProvider. + */ export class StaticLocationProcessor implements StaticLocationProcessor { static fromConfig(config: Config): StaticLocationProcessor { const locations: LocationSpec[] = []; @@ -45,7 +48,7 @@ export class StaticLocationProcessor implements StaticLocationProcessor { } for (const staticLocation of this.staticLocations) { - emit(result.location(staticLocation, false)); + emit(result.location(staticLocation)); } return true; diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts index 397d259bae..35e24ed4cb 100644 --- a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.test.ts @@ -25,14 +25,11 @@ describe('BitbucketRepositoryParser', () => { 'https://bitbucket.mycompany.com/projects/project-key/repos/repo-slug/browse'; const path = '/catalog-info.yaml'; const expected = [ - results.location( - { - type: 'url', - target: `${browseUrl}${path}`, - presence: 'optional', - }, - true, - ), + results.location({ + type: 'url', + target: `${browseUrl}${path}`, + presence: 'optional', + }), ]; const actual = await defaultRepositoryParser({ integration: {} as BitbucketIntegration, diff --git a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts index 34a9284b3e..3407fae16a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts +++ b/plugins/catalog-backend/src/ingestion/processors/bitbucket/BitbucketRepositoryParser.ts @@ -26,15 +26,12 @@ export type BitbucketRepositoryParser = (options: { export const defaultRepositoryParser: BitbucketRepositoryParser = async function* defaultRepositoryParser({ target }) { - yield results.location( - { - type: 'url', - target: target, - presence: 'optional', - }, + yield results.location({ + type: 'url', + target: target, // Not all locations may actually exist, since the user defined them as a wildcard pattern. // Thus, we emit them as optional and let the downstream processor find them while not outputting // an error if it couldn't. - true, - ); + presence: 'optional', + }); }; diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index 63feac51af..36f85647d3 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -18,8 +18,6 @@ import * as results from './results'; export { AnnotateLocationEntityProcessor } from './AnnotateLocationEntityProcessor'; export { AnnotateScmSlugEntityProcessor } from './AnnotateScmSlugEntityProcessor'; -export { AwsOrganizationCloudAccountProcessor } from './AwsOrganizationCloudAccountProcessor'; -export type { AwsOrganizationProviderConfig } from './awsOrganization/config'; export { AwsS3DiscoveryProcessor } from './AwsS3DiscoveryProcessor'; export { BitbucketDiscoveryProcessor } from './BitbucketDiscoveryProcessor'; export { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor'; diff --git a/plugins/catalog-backend/src/ingestion/processors/results.ts b/plugins/catalog-backend/src/ingestion/processors/results.ts index 5b6f07bae4..2862c95119 100644 --- a/plugins/catalog-backend/src/ingestion/processors/results.ts +++ b/plugins/catalog-backend/src/ingestion/processors/results.ts @@ -15,12 +15,9 @@ */ import { InputError, NotFoundError } from '@backstage/errors'; -import { - Entity, - EntityRelationSpec, - LocationSpec, -} from '@backstage/catalog-model'; +import { Entity, LocationSpec } from '@backstage/catalog-model'; import { CatalogProcessorResult } from './types'; +import { EntityRelationSpec } from '../../processing/types'; export function notFoundError( atLocation: LocationSpec, @@ -53,7 +50,7 @@ export function generalError( export function location( newLocation: LocationSpec, - optional: boolean, + optional?: boolean, ): CatalogProcessorResult { return { type: 'location', location: newLocation, optional }; } diff --git a/plugins/catalog-backend/src/ingestion/processors/types.ts b/plugins/catalog-backend/src/ingestion/processors/types.ts index 3e4e24b0fe..873fef842f 100644 --- a/plugins/catalog-backend/src/ingestion/processors/types.ts +++ b/plugins/catalog-backend/src/ingestion/processors/types.ts @@ -14,19 +14,15 @@ * limitations under the License. */ -import { - Entity, - EntityRelationSpec, - LocationSpec, -} from '@backstage/catalog-model'; +import { Entity, LocationSpec } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/types'; +import { EntityRelationSpec } from '../../processing/types'; export type CatalogProcessor = { /** * A unique identifier for the Catalog Processor. - * It's strongly recommended to implement getProcessorName as this method will be required in the future. */ - getProcessorName?(): string; + getProcessorName(): string; /** * Reads the contents of a location. @@ -159,7 +155,8 @@ export type CatalogProcessorEmit = (generated: CatalogProcessorResult) => void; export type CatalogProcessorLocationResult = { type: 'location'; location: LocationSpec; - optional: boolean; + /** @deprecated Set `location.presence = 'optional'` instead */ + optional?: boolean; }; export type CatalogProcessorEntityResult = { diff --git a/plugins/catalog-backend/src/ingestion/processors/util/parse.ts b/plugins/catalog-backend/src/ingestion/processors/util/parse.ts index c9c6c79311..a6aba7e1f9 100644 --- a/plugins/catalog-backend/src/ingestion/processors/util/parse.ts +++ b/plugins/catalog-backend/src/ingestion/processors/util/parse.ts @@ -17,7 +17,7 @@ import { Entity, LocationSpec, - stringifyLocationReference, + stringifyLocationRef, } from '@backstage/catalog-model'; import lodash from 'lodash'; import yaml from 'yaml'; @@ -32,7 +32,7 @@ export function* parseEntityYaml( try { documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d); } catch (e) { - const loc = stringifyLocationReference(location); + const loc = stringifyLocationRef(location); const message = `Failed to parse YAML at ${loc}, ${e}`; yield result.generalError(location, message); return; @@ -40,7 +40,7 @@ export function* parseEntityYaml( for (const document of documents) { if (document.errors?.length) { - const loc = stringifyLocationReference(location); + const loc = stringifyLocationRef(location); const message = `YAML error at ${loc}, ${document.errors[0]}`; yield result.generalError(location, message); } else { diff --git a/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts index b1d44a55b5..20e9966bd1 100644 --- a/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts +++ b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts @@ -14,9 +14,9 @@ * limitations under the License. */ import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, Entity, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { @@ -178,8 +178,8 @@ export function withLocations( { metadata: { annotations: { - [LOCATION_ANNOTATION]: location, - [ORIGIN_LOCATION_ANNOTATION]: location, + [ANNOTATION_LOCATION]: location, + [ANNOTATION_ORIGIN_LOCATION]: location, }, }, }, diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts index 5ae4d58ec7..bdfc623278 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts @@ -16,12 +16,12 @@ import { getVoidLogger } from '@backstage/backend-common'; import { + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, Entity, EntityPolicies, LocationEntity, LocationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { ScmIntegrations } from '@backstage/integration'; import { @@ -82,8 +82,8 @@ describe('DefaultCatalogProcessingOrchestrator', () => { metadata: { name: 'my-foo-bar', annotations: { - [LOCATION_ANNOTATION]: 'url:./here', - [ORIGIN_LOCATION_ANNOTATION]: 'url:./there', + [ANNOTATION_LOCATION]: 'url:./here', + [ANNOTATION_ORIGIN_LOCATION]: 'url:./there', }, }, }; @@ -128,8 +128,8 @@ describe('DefaultCatalogProcessingOrchestrator', () => { metadata: { name: 'my-new-foo-bar', annotations: { - [LOCATION_ANNOTATION]: 'url:./new-place', - [ORIGIN_LOCATION_ANNOTATION]: 'url:./there', + [ANNOTATION_LOCATION]: 'url:./new-place', + [ANNOTATION_ORIGIN_LOCATION]: 'url:./there', }, }, }, @@ -196,8 +196,8 @@ describe('DefaultCatalogProcessingOrchestrator', () => { metadata: { name: 'l', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:https://example.com/origin.yaml', - [LOCATION_ANNOTATION]: 'url:https://example.com/origin.yaml', + [ANNOTATION_ORIGIN_LOCATION]: 'url:https://example.com/origin.yaml', + [ANNOTATION_LOCATION]: 'url:https://example.com/origin.yaml', }, }, spec: { @@ -208,6 +208,7 @@ describe('DefaultCatalogProcessingOrchestrator', () => { const integrations = ScmIntegrations.fromConfig(new ConfigReader({})); const processor: jest.Mocked = { + getProcessorName: jest.fn(), validateEntityKind: jest.fn(async () => true), readLocation: jest.fn(async (_l, _o, emit) => { emit(results.entity({ type: 't', target: 't' }, entity)); diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts index 756b6a3639..105121ae2a 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts @@ -19,9 +19,9 @@ import { EntityPolicy, LocationEntity, LocationSpec, - parseLocationReference, + parseLocationRef, stringifyEntityRef, - stringifyLocationReference, + stringifyLocationRef, } from '@backstage/catalog-model'; import { assertError, @@ -119,10 +119,8 @@ export class DefaultCatalogProcessingOrchestrator // source-location? - maybe probably doesn't exist yet? const context: Context = { entityRef: stringifyEntityRef(entity), - location: parseLocationReference(getEntityLocationRef(entity)), - originLocation: parseLocationReference( - getEntityOriginLocationRef(entity), - ), + location: parseLocationRef(getEntityLocationRef(entity)), + originLocation: parseLocationRef(getEntityOriginLocationRef(entity)), cache, collector, }; @@ -149,9 +147,9 @@ export class DefaultCatalogProcessingOrchestrator throw new NotAllowedError( `Entity ${stringifyEntityRef( deferredEntity.entity, - )} at ${stringifyLocationReference( + )} at ${stringifyLocationRef( context.location, - )}, originated at ${stringifyLocationReference( + )}, originated at ${stringifyLocationRef( context.originLocation, )}, is not of an allowed kind for that location`, ); diff --git a/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts index e7f9fb313b..71631b13d8 100644 --- a/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts @@ -21,7 +21,11 @@ class MyProcessor implements CatalogProcessor { getProcessorName = () => 'my-processor'; } -class OtherProcessor implements CatalogProcessor {} +class OtherProcessor implements CatalogProcessor { + getProcessorName(): string { + return 'OtherProcessor'; + } +} describe('ProcessorCacheManager', () => { const myProcessor = new MyProcessor(); diff --git a/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts index 472d6453ce..ab95fcedb7 100644 --- a/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts @@ -104,7 +104,7 @@ export class ProcessorCacheManager { key?: string, ): CatalogProcessorCache { // constructor name will be deprecated in the future when we make `getProcessorName` required in the implementation - const name = processor.getProcessorName?.() ?? processor.constructor.name; + const name = processor.getProcessorName(); const cache = this.caches.get(name); if (cache) { return key ? cache.withKey(key) : cache; diff --git a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts index 4ac356f706..351e68882b 100644 --- a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts @@ -16,16 +16,15 @@ import { Entity, - EntityRelationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, - stringifyLocationReference, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, + stringifyLocationRef, } from '@backstage/catalog-model'; import { assertError } from '@backstage/errors'; import { Logger } from 'winston'; import { CatalogProcessorResult } from '../ingestion'; import { locationSpecToLocationEntity } from '../util/conversion'; -import { DeferredEntity } from './types'; +import { DeferredEntity, EntityRelationSpec } from './types'; import { getEntityLocationRef, getEntityOriginLocationRef, @@ -82,7 +81,7 @@ export class ProcessorOutputCollector { return; } - const location = stringifyLocationReference(i.location); + const location = stringifyLocationRef(i.location); // Note that at this point, we have only validated the envelope part of // the entity data. Annotations are not part of that, so we have to be @@ -98,8 +97,8 @@ export class ProcessorOutputCollector { ...entity.metadata, annotations: { ...annotations, - [ORIGIN_LOCATION_ANNOTATION]: originLocation, - [LOCATION_ANNOTATION]: location, + [ANNOTATION_ORIGIN_LOCATION]: originLocation, + [ANNOTATION_LOCATION]: location, }, }, }; diff --git a/plugins/catalog-backend/src/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts index dc8b07eceb..83f8a9f566 100644 --- a/plugins/catalog-backend/src/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -19,6 +19,7 @@ export type { CatalogProcessingEngine, EntityProcessingRequest, EntityProcessingResult, + EntityRelationSpec, DeferredEntity, } from './types'; export { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; diff --git a/plugins/catalog-backend/src/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts index 7fb1157d3b..33d8ed8771 100644 --- a/plugins/catalog-backend/src/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -14,9 +14,31 @@ * limitations under the License. */ -import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; +import { Entity, EntityName } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; +/** + * Holds the relation data for entities. + * + * @public + */ +export type EntityRelationSpec = { + /** + * The source entity of this relation. + */ + source: EntityName; + + /** + * The type of the relation. + */ + type: string; + + /** + * The target entity of this relation. + */ + target: EntityName; +}; + export type EntityProcessingRequest = { entity: Entity; state?: JsonObject; // Versions for multiple deployments etc diff --git a/plugins/catalog-backend/src/processing/util.ts b/plugins/catalog-backend/src/processing/util.ts index 9f5f23ed09..a4fa984dc1 100644 --- a/plugins/catalog-backend/src/processing/util.ts +++ b/plugins/catalog-backend/src/processing/util.ts @@ -20,8 +20,8 @@ import { entitySchemaValidator, LocationEntity, LocationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, stringifyEntityRef, } from '@backstage/catalog-model'; import { JsonObject, JsonValue } from '@backstage/types'; @@ -34,7 +34,7 @@ export function isLocationEntity(entity: Entity): entity is LocationEntity { } export function getEntityLocationRef(entity: Entity): string { - const ref = entity.metadata.annotations?.[LOCATION_ANNOTATION]; + const ref = entity.metadata.annotations?.[ANNOTATION_LOCATION]; if (!ref) { const entityRef = stringifyEntityRef(entity); throw new InputError(`Entity '${entityRef}' does not have a location`); @@ -43,7 +43,7 @@ export function getEntityLocationRef(entity: Entity): string { } export function getEntityOriginLocationRef(entity: Entity): string { - const ref = entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION]; + const ref = entity.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION]; if (!ref) { const entityRef = stringifyEntityRef(entity); throw new InputError( diff --git a/plugins/catalog-backend/src/providers/DefaultLocationStore.ts b/plugins/catalog-backend/src/providers/DefaultLocationStore.ts index 9214cd0bc1..f93afedbaa 100644 --- a/plugins/catalog-backend/src/providers/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/providers/DefaultLocationStore.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { Location, LocationSpec } from '@backstage/catalog-model'; +import { LocationSpec } from '@backstage/catalog-model'; +import { Location } from '@backstage/catalog-client'; import { ConflictError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 93ef6968d1..8e72a265af 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -28,7 +28,7 @@ import { Config } from '@backstage/config'; import { CatalogApi, CatalogClient, - CatalogEntitiesRequest, + GetEntitiesRequest, } from '@backstage/catalog-client'; import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common'; @@ -43,7 +43,7 @@ export interface CatalogEntityDocument extends IndexableDocument { export class DefaultCatalogCollator implements DocumentCollator { protected discovery: PluginEndpointDiscovery; protected locationTemplate: string; - protected filter?: CatalogEntitiesRequest['filter']; + protected filter?: GetEntitiesRequest['filter']; protected readonly catalogClient: CatalogApi; public readonly type: string = 'software-catalog'; public readonly visibilityPermission = catalogEntityReadPermission; @@ -54,7 +54,7 @@ export class DefaultCatalogCollator implements DocumentCollator { options: { discovery: PluginEndpointDiscovery; tokenManager: TokenManager; - filter?: CatalogEntitiesRequest['filter']; + filter?: GetEntitiesRequest['filter']; }, ) { return new DefaultCatalogCollator({ @@ -66,7 +66,7 @@ export class DefaultCatalogCollator implements DocumentCollator { discovery: PluginEndpointDiscovery; tokenManager: TokenManager; locationTemplate?: string; - filter?: CatalogEntitiesRequest['filter']; + filter?: GetEntitiesRequest['filter']; catalogClient?: CatalogApi; }) { const { discovery, locationTemplate, filter, catalogClient, tokenManager } = diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index 156db8e8ce..1f0e5ea644 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -30,6 +30,7 @@ describe('AuthorizedEntitiesCatalog', () => { entities: jest.fn(), removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), + facets: jest.fn(), }; const fakePermissionApi = { authorize: jest.fn(), @@ -254,4 +255,54 @@ describe('AuthorizedEntitiesCatalog', () => { }); }); }); + + describe('facets', () => { + it('returns empty response on DENY', async () => { + fakePermissionApi.authorize.mockResolvedValue([ + { result: AuthorizeResult.DENY }, + ]); + const catalog = createCatalog(); + + expect( + await catalog.facets({ + facets: ['a'], + authorizationToken: 'abcd', + }), + ).toEqual({ + facets: { a: [] }, + }); + }); + + it('calls underlying catalog method with correct filter on CONDITIONAL', async () => { + fakePermissionApi.authorize.mockResolvedValue([ + { + result: AuthorizeResult.CONDITIONAL, + conditions: { rule: 'IS_ENTITY_KIND', params: [['b']] }, + }, + ]); + const catalog = createCatalog(isEntityKind); + + await catalog.facets({ facets: ['a'], authorizationToken: 'abcd' }); + + expect(fakeCatalog.facets).toHaveBeenCalledWith({ + facets: ['a'], + authorizationToken: 'abcd', + filter: { key: 'kind', values: ['b'] }, + }); + }); + + it('calls underlying catalog method on ALLOW', async () => { + fakePermissionApi.authorize.mockResolvedValue([ + { result: AuthorizeResult.ALLOW }, + ]); + const catalog = createCatalog(); + + await catalog.facets({ facets: ['a'], authorizationToken: 'abcd' }); + + expect(fakeCatalog.facets).toHaveBeenCalledWith({ + facets: ['a'], + authorizationToken: 'abcd', + }); + }); + }); }); diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index 99fc3ebc8e..2f94e23303 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -30,6 +30,8 @@ import { EntitiesRequest, EntitiesResponse, EntityAncestryResponse, + EntityFacetsRequest, + EntityFacetsResponse, EntityFilter, } from '../catalog/types'; import { basicEntityFilter } from './request/basicEntityFilter'; @@ -151,6 +153,35 @@ export class AuthorizedEntitiesCatalog implements EntitiesCatalog { }; } + async facets(request: EntityFacetsRequest): Promise { + const authorizeDecision = ( + await this.permissionApi.authorize( + [{ permission: catalogEntityReadPermission }], + { token: request?.authorizationToken }, + ) + )[0]; + + if (authorizeDecision.result === AuthorizeResult.DENY) { + return { + facets: Object.fromEntries(request.facets.map(f => [f, []])), + }; + } + + if (authorizeDecision.result === AuthorizeResult.CONDITIONAL) { + const permissionFilter: EntityFilter = this.transformConditions( + authorizeDecision.conditions, + ); + return this.entitiesCatalog.facets({ + ...request, + filter: request?.filter + ? { allOf: [permissionFilter, request.filter] } + : permissionFilter, + }); + } + + return this.entitiesCatalog.facets(request); + } + private findParents( entityRef: string, allAncestryItems: { entity: Entity; parentEntityRefs: string[] }[], diff --git a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts index 1ae2833cd0..13557102c9 100644 --- a/plugins/catalog-backend/src/service/AuthorizedLocationService.ts +++ b/plugins/catalog-backend/src/service/AuthorizedLocationService.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { LocationSpec, Location, Entity } from '@backstage/catalog-model'; +import { Location } from '@backstage/catalog-client'; +import { LocationSpec, Entity } from '@backstage/catalog-model'; import { NotAllowedError, NotFoundError } from '@backstage/errors'; import { catalogLocationCreatePermission, diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts index d6d4e957f6..7094cfd1c2 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.test.ts @@ -535,4 +535,129 @@ describe('DefaultEntitiesCatalog', () => { }, ); }); + + describe('facets', () => { + it.each(databases.eachSupportedId())( + 'can filter and collect properly', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'one' }, + spec: {}, + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { name: 'two' }, + spec: {}, + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k2', + metadata: { name: 'two' }, + spec: {}, + }); + const catalog = new DefaultEntitiesCatalog(knex); + + await expect(catalog.facets({ facets: ['kind'] })).resolves.toEqual({ + facets: { + kind: [ + { value: 'k', count: 2 }, + { value: 'k2', count: 1 }, + ], + }, + }); + }, + ); + + it.each(databases.eachSupportedId())( + 'can match on annotations and labels with dots in them', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'one', + annotations: { 'a.b/c.d': 'annotation1' }, + labels: { 'e.f/g.h': 'label1' }, + }, + spec: {}, + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'two', + annotations: { 'a.b/c.d': 'annotation2' }, + labels: { 'e.f/g.h': 'label2' }, + }, + spec: {}, + }); + const catalog = new DefaultEntitiesCatalog(knex); + + await expect( + catalog.facets({ + facets: ['metadata.annotations.a.b/c.d', 'metadata.labels.e.f/g.h'], + }), + ).resolves.toEqual({ + facets: { + 'metadata.annotations.a.b/c.d': [ + { value: 'annotation1', count: 1 }, + { value: 'annotation2', count: 1 }, + ], + 'metadata.labels.e.f/g.h': [ + { value: 'label1', count: 1 }, + { value: 'label2', count: 1 }, + ], + }, + }); + }, + ); + + it.each(databases.eachSupportedId())( + 'can match on strings in arrays', + async databaseId => { + const { knex } = await createDatabase(databaseId); + + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'one', + tags: ['java', 'rust'], + }, + spec: {}, + }); + await addEntityToSearch(knex, { + apiVersion: 'a', + kind: 'k', + metadata: { + name: 'two', + tags: ['java', 'node'], + }, + spec: {}, + }); + const catalog = new DefaultEntitiesCatalog(knex); + + await expect( + catalog.facets({ + facets: ['metadata.tags'], + }), + ).resolves.toEqual({ + facets: { + 'metadata.tags': expect.arrayContaining([ + { value: 'java', count: 2 }, + { value: 'rust', count: 1 }, + { value: 'node', count: 1 }, + ]), + }, + }); + }, + ); + }); }); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 6979f94ba7..1ac70bda30 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -17,21 +17,24 @@ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { InputError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; +import lodash from 'lodash'; import { EntitiesCatalog, EntitiesRequest, EntitiesResponse, - EntityAncestryResponse, - EntityPagination, - EntityFilter, EntitiesSearchFilter, + EntityAncestryResponse, + EntityFacetsRequest, + EntityFacetsResponse, + EntityFilter, + EntityPagination, } from '../catalog/types'; import { DbFinalEntitiesRow, + DbPageInfo, DbRefreshStateReferencesRow, DbRefreshStateRow, DbSearchRow, - DbPageInfo, } from '../database/tables'; function parsePagination(input?: EntityPagination): { @@ -295,4 +298,49 @@ export class DefaultEntitiesCatalog implements EntitiesCatalog { items, }; } + + async facets(request: EntityFacetsRequest): Promise { + const { entities } = await this.entities({ + filter: request.filter, + authorizationToken: request.authorizationToken, + }); + + const facets: EntityFacetsResponse['facets'] = {}; + + for (const facet of request.facets) { + const values = entities + .map(entity => { + // TODO(freben): Generalize this code to handle any field that may + // have dots in its key? + if (facet.startsWith('metadata.annotations.')) { + return entity.metadata.annotations?.[ + facet.substring('metadata.annotations.'.length) + ]; + } else if (facet.startsWith('metadata.labels.')) { + return entity.metadata.labels?.[ + facet.substring('metadata.labels.'.length) + ]; + } + return lodash.get(entity, facet); + }) + .flatMap(field => { + if (typeof field === 'string') { + return [field]; + } else if (Array.isArray(field)) { + return field.filter(i => typeof i === 'string'); + } + return []; + }) + .sort(); + + const counts = lodash.countBy(values, lodash.identity); + + facets[facet] = Object.entries(counts).map(([value, count]) => ({ + value, + count, + })); + } + + return { facets }; + } } diff --git a/plugins/catalog-backend/src/service/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts index 8dd2274842..8bc02e24f6 100644 --- a/plugins/catalog-backend/src/service/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -15,12 +15,12 @@ */ import { Entity, - Location, LocationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, stringifyEntityRef, } from '@backstage/catalog-model'; +import { Location } from '@backstage/catalog-client'; import { CatalogProcessingOrchestrator, DeferredEntity, @@ -112,8 +112,8 @@ export class DefaultLocationService implements LocationService { }), namespace: 'default', annotations: { - [LOCATION_ANNOTATION]: `${spec.type}:${spec.target}`, - [ORIGIN_LOCATION_ANNOTATION]: `${spec.type}:${spec.target}`, + [ANNOTATION_LOCATION]: `${spec.type}:${spec.target}`, + [ANNOTATION_ORIGIN_LOCATION]: `${spec.type}:${spec.target}`, }, }, spec: { diff --git a/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts index 1876e59f95..84bfde1259 100644 --- a/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts @@ -213,6 +213,7 @@ describe('Refresh integration', () => { await engine.stop(); }, + 60_000, ); it.each(databases.eachSupportedId())( @@ -264,6 +265,7 @@ describe('Refresh integration', () => { await engine.stop(); }, + 60_000, ); it.each(databases.eachSupportedId())( @@ -323,5 +325,6 @@ describe('Refresh integration', () => { await engine.stop(); }, + 60_000, ); }); diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 205be01b42..755134c3d9 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -17,7 +17,8 @@ import { getVoidLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { NotFoundError } from '@backstage/errors'; -import type { Entity, LocationSpec, Location } from '@backstage/catalog-model'; +import type { Location } from '@backstage/catalog-client'; +import type { Entity, LocationSpec } from '@backstage/catalog-model'; import express from 'express'; import request from 'supertest'; import { EntitiesCatalog } from '../catalog'; @@ -39,6 +40,7 @@ describe('createRouter readonly disabled', () => { entities: jest.fn(), removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), + facets: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -393,6 +395,7 @@ describe('createRouter readonly enabled', () => { entities: jest.fn(), removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), + facets: jest.fn(), }; locationService = { getLocation: jest.fn(), @@ -577,6 +580,7 @@ describe('NextRouter permissioning', () => { entities: jest.fn(), removeEntityByUid: jest.fn(), entityAncestry: jest.fn(), + facets: jest.fn(), }; locationService = { getLocation: jest.fn(), diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts index ab123238c7..a4d911a421 100644 --- a/plugins/catalog-backend/src/service/createRouter.ts +++ b/plugins/catalog-backend/src/service/createRouter.ts @@ -15,11 +15,7 @@ */ import { errorHandler } from '@backstage/backend-common'; -import { - analyzeLocationSchema, - locationSpecSchema, - stringifyEntityRef, -} from '@backstage/catalog-model'; +import { stringifyEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { NotFoundError } from '@backstage/errors'; import express from 'express'; @@ -34,8 +30,14 @@ import { parseEntityPaginationParams, parseEntityTransformParams, } from './request'; -import { disallowReadonlyMode, validateRequestBody } from './util'; +import { + disallowReadonlyMode, + locationSpec, + validateRequestBody, +} from './util'; import { RefreshOptions, LocationService, RefreshService } from './types'; +import { z } from 'zod'; +import { parseEntityFacetParams } from './request/parseEntityFacetParams'; /** * Options used by {@link createRouter}. @@ -159,13 +161,21 @@ export async function createRouter( const response = await entitiesCatalog.entityAncestry(entityRef); res.status(200).json(response); }, - ); + ) + .get('/entity-facets', async (req, res) => { + const response = await entitiesCatalog.facets({ + filter: parseEntityFilterParams(req.query), + facets: parseEntityFacetParams(req.query), + authorizationToken: getBearerToken(req.header('authorization')), + }); + res.status(200).json(response); + }); } if (locationService) { router .post('/locations', async (req, res) => { - const input = await validateRequestBody(req, locationSpecSchema); + const location = await validateRequestBody(req, locationSpec); const dryRun = yn(req.query.dryRun, { default: false }); // when in dryRun addLocation is effectively a read operation so we don't @@ -174,7 +184,7 @@ export async function createRouter( disallowReadonlyMode(readonlyEnabled); } - const output = await locationService.createLocation(input, dryRun, { + const output = await locationService.createLocation(location, dryRun, { authorizationToken: getBearerToken(req.header('authorization')), }); res.status(201).json(output); @@ -206,8 +216,12 @@ export async function createRouter( if (locationAnalyzer) { router.post('/analyze-location', async (req, res) => { - const input = await validateRequestBody(req, analyzeLocationSchema); - const output = await locationAnalyzer.analyzeLocation(input); + const body = await validateRequestBody( + req, + z.object({ location: locationSpec }), + ); + const schema = z.object({ location: locationSpec }); + const output = await locationAnalyzer.analyzeLocation(schema.parse(body)); res.status(200).json(output); }); } diff --git a/plugins/catalog-backend/src/service/request/parseEntityFacetParams.ts b/plugins/catalog-backend/src/service/request/parseEntityFacetParams.ts new file mode 100644 index 0000000000..00493f068f --- /dev/null +++ b/plugins/catalog-backend/src/service/request/parseEntityFacetParams.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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/errors'; +import { parseStringsParam } from './common'; + +/** + * Parses the facets part of a facet query, like + * /entity-facets?filter=metadata.namespace=default,kind=Component&facet=metadata.namespace + */ +export function parseEntityFacetParams( + params: Record, +): string[] { + // Each facet string is on the form a.b.c + const facetStrings = parseStringsParam(params.facet, 'facet'); + if (facetStrings) { + const filtered = facetStrings.filter(Boolean); + if (filtered.length) { + return filtered; + } + } + + throw new InputError('Missing facet parameter'); +} diff --git a/plugins/catalog-backend/src/service/types.ts b/plugins/catalog-backend/src/service/types.ts index 02d234b6a8..c923949a04 100644 --- a/plugins/catalog-backend/src/service/types.ts +++ b/plugins/catalog-backend/src/service/types.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { Entity, LocationSpec, Location } from '@backstage/catalog-model'; +import { Entity, LocationSpec } from '@backstage/catalog-model'; +import { Location } from '@backstage/catalog-client'; export interface LocationService { createLocation( diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index 7cc2d6618a..09f1c2d8cf 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -17,7 +17,7 @@ import { InputError, NotAllowedError } from '@backstage/errors'; import { Request } from 'express'; import lodash from 'lodash'; -import yup from 'yup'; +import { z } from 'zod'; export async function requireRequestBody(req: Request): Promise { const contentType = req.header('content-type'); @@ -40,19 +40,24 @@ export async function requireRequestBody(req: Request): Promise { return body; } +export const locationSpec = z + .object({ + type: z.string(), + target: z.string(), + presence: z.literal('required').or(z.literal('optional')).optional(), + }) + .strict(); // no unknown keys; + export async function validateRequestBody( req: Request, - schema: yup.AnySchema, + schema: z.Schema, ): Promise { const body = await requireRequestBody(req); - try { - await schema.validate(body, { strict: true }); + return await schema.parse(body); } catch (e) { throw new InputError(`Malformed request: ${e}`); } - - return body as unknown as T; } export function disallowReadonlyMode(readonly: boolean) { diff --git a/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts index 58551a461f..173538f18f 100644 --- a/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts +++ b/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { buildEntitySearch, mapToRows, traverse } from './buildEntitySearch'; describe('buildEntitySearch', () => { @@ -133,7 +133,7 @@ describe('buildEntitySearch', () => { { entity_id: 'eid', key: 'metadata.namespace', - value: ENTITY_DEFAULT_NAMESPACE, + value: DEFAULT_NAMESPACE, }, ]); }); @@ -157,7 +157,7 @@ describe('buildEntitySearch', () => { { entity_id: 'eid', key: 'metadata.namespace', - value: ENTITY_DEFAULT_NAMESPACE, + value: DEFAULT_NAMESPACE, }, { entity_id: 'eid', key: 'relations.t1', value: 'k:ns/a' }, { entity_id: 'eid', key: 'relations.t2', value: 'k:ns/b' }, diff --git a/plugins/catalog-backend/src/stitching/buildEntitySearch.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.ts index 84c6036013..d0506e8998 100644 --- a/plugins/catalog-backend/src/stitching/buildEntitySearch.ts +++ b/plugins/catalog-backend/src/stitching/buildEntitySearch.ts @@ -16,7 +16,7 @@ import { Entity, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; @@ -174,7 +174,7 @@ export function buildEntitySearch( // Namespace not specified has the default value "default", so we want to // match on that as well if (!entity.metadata.namespace) { - raw.push({ key: 'metadata.namespace', value: ENTITY_DEFAULT_NAMESPACE }); + raw.push({ key: 'metadata.namespace', value: DEFAULT_NAMESPACE }); } // Visit relations diff --git a/plugins/catalog-backend/src/util/conversion.ts b/plugins/catalog-backend/src/util/conversion.ts index 559a472c25..9dd5ce7986 100644 --- a/plugins/catalog-backend/src/util/conversion.ts +++ b/plugins/catalog-backend/src/util/conversion.ts @@ -18,10 +18,10 @@ import { Entity, LocationEntityV1alpha1, LocationSpec, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, stringifyEntityRef, - stringifyLocationReference, + stringifyLocationRef, } from '@backstage/catalog-model'; import { createHash } from 'crypto'; @@ -40,31 +40,31 @@ export function locationSpecToLocationEntity( let originLocation: string; if (parentEntity) { const maybeOwnLocation = - parentEntity.metadata.annotations?.[LOCATION_ANNOTATION]; + parentEntity.metadata.annotations?.[ANNOTATION_LOCATION]; if (!maybeOwnLocation) { throw new Error( `Parent entity '${stringifyEntityRef( parentEntity, - )}' of location '${stringifyLocationReference( + )}' of location '${stringifyLocationRef( location, )}' does not have a location annotation`, ); } ownLocation = maybeOwnLocation; const maybeOriginLocation = - parentEntity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION]; + parentEntity.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION]; if (!maybeOriginLocation) { throw new Error( `Parent entity '${stringifyEntityRef( parentEntity, - )}' of location '${stringifyLocationReference( + )}' of location '${stringifyLocationRef( location, )}' does not have an origin location annotation`, ); } originLocation = maybeOriginLocation; } else { - ownLocation = stringifyLocationReference(location); + ownLocation = stringifyLocationRef(location); originLocation = ownLocation; } @@ -74,8 +74,8 @@ export function locationSpecToLocationEntity( metadata: { name: locationSpecToMetadataName(location), annotations: { - [LOCATION_ANNOTATION]: ownLocation, - [ORIGIN_LOCATION_ANNOTATION]: originLocation, + [ANNOTATION_LOCATION]: ownLocation, + [ANNOTATION_ORIGIN_LOCATION]: originLocation, }, }, spec: { diff --git a/plugins/catalog-backend/src/util/index.ts b/plugins/catalog-backend/src/util/index.ts index 2e592fb8df..13a9c84b0f 100644 --- a/plugins/catalog-backend/src/util/index.ts +++ b/plugins/catalog-backend/src/util/index.ts @@ -16,4 +16,3 @@ export * from './runPeriodically'; export * from './RecursivePartial'; -export * from './timing'; diff --git a/plugins/catalog-backend/src/util/runPeriodically.ts b/plugins/catalog-backend/src/util/runPeriodically.ts index 2f3104e221..d3bf5d21d5 100644 --- a/plugins/catalog-backend/src/util/runPeriodically.ts +++ b/plugins/catalog-backend/src/util/runPeriodically.ts @@ -23,6 +23,7 @@ * @param delayMs - The delay between a completed function invocation and the * next. * @returns A function that, when called, stops the invocation loop. + * @deprecated use \@backstage/backend-tasks package instead. */ export function runPeriodically(fn: () => any, delayMs: number): () => void { let cancel: () => void; diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index a236e55857..337bd6854c 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-common +## 0.1.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/plugin-permission-common@0.5.1 + +## 0.1.3 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/plugin-permission-common@0.5.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index 4b94809ed5..4b95fd3524 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "0.1.2", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,18 +25,18 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test --passWithNoTests", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/plugin-permission-common": "^0.4.0" + "@backstage/plugin-permission-common": "^0.5.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 0bb6e7224a..19a284d2fd 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-graph +## 0.2.11 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.10 ### Patch Changes diff --git a/plugins/catalog-graph/dev/index.tsx b/plugins/catalog-graph/dev/index.tsx index ed14e5fce9..3ff9285a81 100644 --- a/plugins/catalog-graph/dev/index.tsx +++ b/plugins/catalog-graph/dev/index.tsx @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CatalogListResponse } from '@backstage/catalog-client'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; import { Entity, EntityName, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, RELATION_API_CONSUMED_BY, RELATION_API_PROVIDED_BY, RELATION_CONSUMES_API, @@ -117,7 +117,7 @@ const entities = ( name, }, relations: relations.map(([type, k, n]) => ({ - target: { kind: k, name: n, namespace: ENTITY_DEFAULT_NAMESPACE }, + target: { kind: k, name: n, namespace: DEFAULT_NAMESPACE }, type, })), }; @@ -136,7 +136,7 @@ createDevApp() async getEntityByName(name: EntityName): Promise { return entities[stringifyEntityRef(name)]; }, - async getEntities(): Promise> { + async getEntities(): Promise { return { items: Object.values(entities) }; }, } as Partial as unknown as CatalogApi; diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 541d21f319..1d7d5d41fb 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.10", + "version": "0.2.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,23 +10,26 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -42,10 +45,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx index 7209a516a5..7cebdee692 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx @@ -60,12 +60,12 @@ describe('', () => { getEntityByName: jest.fn(async _ => ({ ...entity, relations: [] })), removeEntityByUid: jest.fn(), getLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; apis = TestApiRegistry.from([catalogApiRef, catalog]); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index 4c7a64a7ce..f98aca0081 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -89,12 +89,12 @@ describe('', () => { getEntityByName: jest.fn(async n => (n.name === 'e' ? entityE : entityC)), removeEntityByUid: jest.fn(), getLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; wrapper = ( diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx index be0c4dc5e5..f16d06f809 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx @@ -150,12 +150,12 @@ describe('', () => { getEntityByName: jest.fn(async n => entities[stringifyEntityRef(n)]), removeEntityByUid: jest.fn(), getLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; Wrapper = ({ children }) => ( diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts index 2f78fd9c17..b272abc654 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model'; import { MouseEvent, useState } from 'react'; @@ -77,7 +77,7 @@ export function useEntityRelationNodesAndEdges({ title: entity.metadata?.title ?? undefined, kind: entity.kind, name: entity.metadata.name, - namespace: entity.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE, + namespace: entity.metadata.namespace ?? DEFAULT_NAMESPACE, focused, color: focused ? 'secondary' : 'primary', }; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts index a60750bab5..a5dc82eab9 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts @@ -32,12 +32,12 @@ describe('useEntityStore', () => { getEntityByName: jest.fn(), removeEntityByUid: jest.fn(), getLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), addLocation: jest.fn(), removeLocationById: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; useApi.mockReturnValue(catalogApi); diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index f2ad5d14b4..d2ca1a5894 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-graphql +## 0.3.3 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/types@0.1.3 + +## 0.3.2 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.3.1 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index b757790275..2d2dc5d1e5 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "An experimental Backstage catalog GraphQL module", - "version": "0.3.1", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,19 +24,19 @@ "graphql" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", "generate:types": "graphql-codegen", - "clean": "backstage-cli clean" + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/types": "^0.1.1", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/types": "^0.1.2", "graphql-modules": "^1.0.0", "apollo-server": "^3.0.0", "graphql": "^16.0.0", @@ -43,8 +46,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@graphql-codegen/cli": "^2.3.1", "@graphql-codegen/typescript": "^2.4.2", "@graphql-codegen/typescript-resolvers": "^2.4.3", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 8c86fd4ca2..25d6cc143f 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-import +## 0.8.2 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- Updated dependencies + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.8.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 7ce6f8524f..79bf9868db 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.8.1", + "version": "0.8.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,25 +24,25 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/config": "^0.1.13", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog-react": "^0.6.14", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/config": "^0.1.14", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog-react": "^0.6.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -57,10 +60,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index fa63825af1..f689c0a883 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -94,12 +94,12 @@ describe('CatalogImportClient', () => { addLocation: jest.fn(), removeLocationById: jest.fn(), getEntityByName: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; let catalogImportClient: CatalogImportClient; diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 8d26657bb3..fc9b35136a 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -39,13 +39,13 @@ describe('', () => { getEntities: jest.fn(), addLocation: jest.fn(), getEntityByName: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const errorApi: jest.Mocked = { diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 65fd275389..fa59393bd9 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-react +## 0.6.15 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- edbc03814a: Replace usage of `serializeEntityRef` with `stringifyEntityRef` +- 244d24ebc4: Import `Location` from the `@backstage/catalog-client` package. +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead + of `@backstage/catalog-model`. +- 98d1aa1ea1: Fix CatalogPage showing all components when owned filter was pre-selected +- 27eccab216: Replaces use of deprecated catalog-model constants. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/plugin-permission-react@0.3.1 + - @backstage/catalog-model@0.10.0 + - @backstage/types@0.1.2 + - @backstage/version-bridge@0.1.2 + ## 0.6.14 ### Patch Changes diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 056f10f135..104472cbfe 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -9,12 +9,12 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { AsyncState } from 'react-use/lib/useAsync'; import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; import { CatalogApi } from '@backstage/catalog-client'; -import { CatalogListResponse } from '@backstage/catalog-client'; import { ComponentEntity } from '@backstage/catalog-model'; import { ComponentProps } from 'react'; import { Context } from 'react'; import { Entity } from '@backstage/catalog-model'; import { EntityName } from '@backstage/catalog-model'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; import { IconButton } from '@material-ui/core'; import { IdentityApi } from '@backstage/core-plugin-api'; import { LinkProps } from '@backstage/core-components'; @@ -66,9 +66,7 @@ export { CATALOG_FILTER_EXISTS }; export { CatalogApi }; -// Warning: (ae-missing-release-tag) "catalogApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const catalogApiRef: ApiRef; // @public (undocumented) @@ -100,51 +98,37 @@ export type CatalogReactUserListPickerClassKey = | 'menuItem' | 'groupWrapper'; -// Warning: (ae-missing-release-tag) "catalogRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated (undocumented) export const catalogRouteRef: RouteRef; // @public (undocumented) -function createDomainColumn(): TableColumn; +export const columnFactories: Readonly<{ + createEntityRefColumn(options: { + defaultKind?: string; + }): TableColumn; + createEntityRelationColumn({ + title, + relation, + defaultKind, + filter: entityFilter, + }: { + title: string; + relation: string; + defaultKind?: string | undefined; + filter?: + | { + kind: string; + } + | undefined; + }): TableColumn; + createOwnerColumn(): TableColumn; + createDomainColumn(): TableColumn; + createSystemColumn(): TableColumn; + createMetadataDescriptionColumn(): TableColumn; + createSpecLifecycleColumn(): TableColumn; + createSpecTypeColumn(): TableColumn; +}>; -// @public (undocumented) -function createEntityRefColumn(options: { - defaultKind?: string; -}): TableColumn; - -// @public (undocumented) -function createEntityRelationColumn({ - title, - relation, - defaultKind, - filter: entityFilter, -}: { - title: string; - relation: string; - defaultKind?: string; - filter?: { - kind: string; - }; -}): TableColumn; - -// @public (undocumented) -function createMetadataDescriptionColumn(): TableColumn; - -// @public (undocumented) -function createOwnerColumn(): TableColumn; - -// @public (undocumented) -function createSpecLifecycleColumn(): TableColumn; - -// @public (undocumented) -function createSpecTypeColumn(): TableColumn; - -// @public (undocumented) -function createSystemColumn(): TableColumn; - -// Warning: (ae-missing-release-tag) "DefaultEntityFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type DefaultEntityFilters = { kind?: EntityKindFilter; @@ -167,13 +151,9 @@ export class DefaultStarredEntitiesApi implements StarredEntitiesApi { toggleStarred(entityRef: string): Promise; } -// Warning: (ae-forgotten-export) The symbol "EntityLoadingStatus" needs to be exported by the entry point index.d.ts -// // @public @deprecated (undocumented) export const EntityContext: Context; -// Warning: (ae-missing-release-tag) "EntityFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type EntityFilter = { getCatalogFilters?: () => Record< @@ -184,9 +164,7 @@ export type EntityFilter = { toQueryValue?: () => string | string[]; }; -// Warning: (ae-missing-release-tag) "EntityKindFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class EntityKindFilter implements EntityFilter { constructor(value: string); // (undocumented) @@ -210,9 +188,7 @@ export interface EntityKindPickerProps { initialFilter?: string; } -// Warning: (ae-missing-release-tag) "EntityLifecycleFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class EntityLifecycleFilter implements EntityFilter { constructor(values: string[]); // (undocumented) @@ -226,24 +202,42 @@ export class EntityLifecycleFilter implements EntityFilter { // @public (undocumented) export const EntityLifecyclePicker: () => JSX.Element | null; -// Warning: (ae-forgotten-export) The symbol "EntityListContextProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "EntityListContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const EntityListContext: React_2.Context< EntityListContextProps | undefined >; -// Warning: (ae-missing-release-tag) "EntityListProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) +export type EntityListContextProps< + EntityFilters extends DefaultEntityFilters = DefaultEntityFilters, +> = { + filters: EntityFilters; + entities: Entity[]; + backendEntities: Entity[]; + updateFilters: ( + filters: + | Partial + | ((prevFilters: EntityFilters) => Partial), + ) => void; + queryParameters: Partial>; + loading: boolean; + error?: Error; +}; + +// @public export const EntityListProvider: ({ children, }: PropsWithChildren<{}>) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityOwnerFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) +export type EntityLoadingStatus = { + entity?: Entity; + loading: boolean; + error?: Error; + refresh?: VoidFunction; +}; + +// @public export class EntityOwnerFilter implements EntityFilter { constructor(values: string[]); // (undocumented) @@ -295,8 +289,6 @@ export type EntityRefLinksProps = { defaultKind?: string; } & Omit; -// Warning: (ae-missing-release-tag) "entityRoute" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated (undocumented) export const entityRoute: RouteRef<{ name: string; @@ -304,17 +296,13 @@ export const entityRoute: RouteRef<{ namespace: string; }>; -// Warning: (ae-missing-release-tag) "entityRouteParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function entityRouteParams(entity: Entity): { readonly kind: string; readonly namespace: string; readonly name: string; }; -// Warning: (ae-missing-release-tag) "entityRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const entityRouteRef: RouteRef<{ name: string; @@ -322,38 +310,48 @@ export const entityRouteRef: RouteRef<{ namespace: string; }>; -// @public (undocumented) +// @public export const EntitySearchBar: () => JSX.Element; -// Warning: (ae-missing-release-tag) "EntitySourceLocation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type EntitySourceLocation = { locationTargetUrl: string; integrationType?: string; }; -// Warning: (ae-missing-release-tag) "EntityTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public -export function EntityTable( - props: EntityTableProps, -): JSX.Element; +export const EntityTable: { + (props: EntityTableProps): JSX.Element; + columns: Readonly<{ + createEntityRefColumn(options: { + defaultKind?: string | undefined; + }): TableColumn; + createEntityRelationColumn({ + title, + relation, + defaultKind, + filter: entityFilter, + }: { + title: string; + relation: string; + defaultKind?: string | undefined; + filter?: + | { + kind: string; + } + | undefined; + }): TableColumn; + createOwnerColumn(): TableColumn; + createDomainColumn(): TableColumn; + createSystemColumn(): TableColumn; + createMetadataDescriptionColumn(): TableColumn; + createSpecLifecycleColumn(): TableColumn; + createSpecTypeColumn(): TableColumn; + }>; + systemEntityColumns: TableColumn[]; + componentEntityColumns: TableColumn[]; +}; -// @public (undocumented) -export namespace EntityTable { - var // Warning: (ae-forgotten-export) The symbol "columnFactories" needs to be exported by the entry point index.d.ts - // - // (undocumented) - columns: typeof columnFactories; - var // (undocumented) - systemEntityColumns: TableColumn[]; - var // (undocumented) - componentEntityColumns: TableColumn[]; -} - -// Warning: (ae-unresolved-link) The @link reference could not be resolved: The reference is ambiguous because "EntityTable" has more than one declaration; you need to add a TSDoc member reference selector -// // @public export interface EntityTableProps { // (undocumented) @@ -368,9 +366,7 @@ export interface EntityTableProps { variant?: 'gridItem'; } -// Warning: (ae-missing-release-tag) "EntityTagFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class EntityTagFilter implements EntityFilter { constructor(values: string[]); // (undocumented) @@ -384,9 +380,7 @@ export class EntityTagFilter implements EntityFilter { // @public (undocumented) export const EntityTagPicker: () => JSX.Element | null; -// Warning: (ae-missing-release-tag) "EntityTextFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class EntityTextFilter implements EntityFilter { constructor(value: string); // (undocumented) @@ -395,9 +389,7 @@ export class EntityTextFilter implements EntityFilter { readonly value: string; } -// Warning: (ae-missing-release-tag) "EntityTypeFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class EntityTypeFilter implements EntityFilter { constructor(value: string | string[]); // (undocumented) @@ -423,26 +415,31 @@ export interface EntityTypePickerProps { initialFilter?: string; } -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "FavoriteEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export const FavoriteEntity: (props: Props) => JSX.Element; +// @public (undocumented) +export type EntityTypeReturn = { + loading: boolean; + error?: Error; + availableTypes: string[]; + selectedTypes: string[]; + setSelectedTypes: (types: string[]) => void; +}; + +// @public +export const FavoriteEntity: (props: FavoriteEntityProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "favoriteEntityIcon" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const favoriteEntityIcon: (isStarred: boolean) => JSX.Element; -// Warning: (ae-missing-release-tag) "favoriteEntityTooltip" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public (undocumented) +export type FavoriteEntityProps = ComponentProps & { + entity: Entity; +}; + // @public (undocumented) export const favoriteEntityTooltip: ( isStarred: boolean, ) => 'Remove from favorites' | 'Add to favorites'; -// Warning: (ae-missing-release-tag) "formatEntityRefTitle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function formatEntityRefTitle( entityRef: Entity | EntityName, @@ -451,18 +448,12 @@ export function formatEntityRefTitle( }, ): string; -// Warning: (ae-missing-release-tag) "getEntityMetadataEditUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getEntityMetadataEditUrl(entity: Entity): string | undefined; -// Warning: (ae-missing-release-tag) "getEntityMetadataViewUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getEntityMetadataViewUrl(entity: Entity): string | undefined; -// Warning: (ae-missing-release-tag) "getEntityRelations" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function getEntityRelations( entity: Entity | undefined, @@ -472,8 +463,6 @@ export function getEntityRelations( }, ): EntityName[]; -// Warning: (ae-missing-release-tag) "getEntitySourceLocation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function getEntitySourceLocation( entity: Entity, @@ -487,8 +476,6 @@ export function InspectEntityDialog(props: { onClose: () => void; }): JSX.Element | null; -// Warning: (ae-missing-release-tag) "isOwnerOf" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function isOwnerOf(owner: Entity, owned: Entity): boolean; @@ -503,8 +490,6 @@ export function loadIdentityOwnerRefs( identityApi: IdentityApi, ): Promise; -// Warning: (ae-missing-release-tag) "MockEntityListContextProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const MockEntityListContextProvider: ({ children, @@ -513,22 +498,16 @@ export const MockEntityListContextProvider: ({ value?: Partial> | undefined; }>) => JSX.Element; -// Warning: (ae-missing-release-tag) "reduceCatalogFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function reduceCatalogFilters( filters: EntityFilter[], ): Record; -// Warning: (ae-missing-release-tag) "reduceEntityFilters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function reduceEntityFilters( filters: EntityFilter[], ): (entity: Entity) => boolean; -// Warning: (ae-missing-release-tag) "rootRoute" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated (undocumented) export const rootRoute: RouteRef; @@ -541,16 +520,18 @@ export interface StarredEntitiesApi { // @public export const starredEntitiesApiRef: ApiRef; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "UnregisterEntityDialog" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const UnregisterEntityDialog: ({ - open, - onConfirm, - onClose, - entity, -}: Props_2) => JSX.Element; +export const UnregisterEntityDialog: ( + props: UnregisterEntityDialogProps, +) => JSX.Element; + +// @public (undocumented) +export type UnregisterEntityDialogProps = { + open: boolean; + onConfirm: () => any; + onClose: () => any; + entity: Entity; +}; // @public export function useEntity(): { @@ -560,8 +541,6 @@ export function useEntity(): { refresh: VoidFunction | undefined; }; -// Warning: (ae-missing-release-tag) "useEntityCompoundName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const useEntityCompoundName: () => { kind: string; @@ -569,23 +548,17 @@ export const useEntityCompoundName: () => { name: string; }; -// Warning: (ae-missing-release-tag) "useEntityFromUrl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const useEntityFromUrl: () => EntityLoadingStatus; -// Warning: (ae-missing-release-tag) "useEntityKinds" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function useEntityKinds(): { error: Error | undefined; loading: boolean; kinds: string[] | undefined; }; -// Warning: (ae-missing-release-tag) "useEntityListProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function useEntityListProvider< EntityFilters extends DefaultEntityFilters = DefaultEntityFilters, >(): EntityListContextProps; @@ -603,25 +576,18 @@ export function useEntityPermission(permission: Permission): { error?: Error; }; -// Warning: (ae-forgotten-export) The symbol "EntityTypeReturn" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "useEntityTypeFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function useEntityTypeFilter(): EntityTypeReturn; // @public export function useOwnedEntities(allowedKinds?: string[]): { loading: boolean; - ownedEntities: CatalogListResponse | undefined; + ownedEntities: GetEntitiesResponse | undefined; }; -// Warning: (ae-missing-release-tag) "useOwnUser" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export function useOwnUser(): AsyncState; -// Warning: (ae-missing-release-tag) "useRelatedEntities" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function useRelatedEntities( entity: Entity, @@ -638,9 +604,7 @@ export function useRelatedEntities( error: Error | undefined; }; -// Warning: (ae-missing-release-tag) "UserListFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export class UserListFilter implements EntityFilter { constructor( value: UserListFilterKind, @@ -659,22 +623,18 @@ export class UserListFilter implements EntityFilter { readonly value: UserListFilterKind; } -// Warning: (ae-missing-release-tag) "UserListFilterKind" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type UserListFilterKind = 'owned' | 'starred' | 'all'; -// Warning: (ae-forgotten-export) The symbol "UserListPickerProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "UserListPicker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const UserListPicker: ({ - initialFilter, - availableFilters, -}: UserListPickerProps) => JSX.Element; +export const UserListPicker: (props: UserListPickerProps) => JSX.Element; + +// @public (undocumented) +export type UserListPickerProps = { + initialFilter?: UserListFilterKind; + availableFilters?: UserListFilterKind[]; +}; -// Warning: (ae-missing-release-tag) "useStarredEntities" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function useStarredEntities(): { starredEntities: Set; @@ -682,8 +642,6 @@ export function useStarredEntities(): { isStarredEntity: (entityOrRef: Entity | EntityName | string) => boolean; }; -// Warning: (ae-missing-release-tag) "useStarredEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export function useStarredEntity(entityOrRef: Entity | EntityName | string): { toggleStarredEntity: () => void; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index d995fdf848..db9e01e593 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "0.6.14", + "version": "0.6.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,24 +24,25 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/types": "^0.1.1", - "@backstage/version-bridge": "^0.1.1", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/types": "^0.1.2", + "@backstage/version-bridge": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -56,10 +60,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/plugin-scaffolder-common": "^0.2.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-react/src/api.ts b/plugins/catalog-react/src/api.ts index 51146b95bf..38e1f618cd 100644 --- a/plugins/catalog-react/src/api.ts +++ b/plugins/catalog-react/src/api.ts @@ -17,6 +17,10 @@ import { CatalogApi } from '@backstage/catalog-client'; import { createApiRef } from '@backstage/core-plugin-api'; +/** + * The API reference for the {@link @backstage/catalog-client#CatalogApi}. + * @public + */ export const catalogApiRef = createApiRef({ id: 'plugin.catalog.service', }); diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx index 8120ececd2..f2c67f1087 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx +++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.tsx @@ -17,7 +17,7 @@ import { Entity, EntityName, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; import React, { forwardRef } from 'react'; import { entityRouteRef } from '../../routes'; @@ -66,8 +66,7 @@ export const EntityRefLink = forwardRef( const routeParams = { kind, - namespace: - namespace?.toLocaleLowerCase('en-US') ?? ENTITY_DEFAULT_NAMESPACE, + namespace: namespace?.toLocaleLowerCase('en-US') ?? DEFAULT_NAMESPACE, name, }; const formattedEntityRefTitle = formatEntityRefTitle(entityRef, { diff --git a/plugins/catalog-react/src/components/EntityRefLink/format.ts b/plugins/catalog-react/src/components/EntityRefLink/format.ts index f3977ccc95..90100245a1 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/format.ts +++ b/plugins/catalog-react/src/components/EntityRefLink/format.ts @@ -17,10 +17,10 @@ import { Entity, EntityName, - ENTITY_DEFAULT_NAMESPACE, - serializeEntityRef, + DEFAULT_NAMESPACE, } from '@backstage/catalog-model'; +/** @public */ export function formatEntityRefTitle( entityRef: Entity | EntityName, opts?: { defaultKind?: string }, @@ -40,18 +40,14 @@ export function formatEntityRefTitle( name = entityRef.name; } - if (namespace === ENTITY_DEFAULT_NAMESPACE) { + if (namespace === DEFAULT_NAMESPACE) { namespace = undefined; } kind = kind.toLocaleLowerCase('en-US'); - - return `${serializeEntityRef({ - kind: - defaultKind && defaultKind.toLocaleLowerCase('en-US') === kind - ? undefined - : kind, - name, - namespace, - })}`; + kind = + defaultKind && defaultKind.toLocaleLowerCase('en-US') === kind + ? undefined + : kind; + return `${kind ? `${kind}:` : ''}${namespace ? `${namespace}/` : ''}${name}`; } diff --git a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx index ec977fada4..f13fb1621f 100644 --- a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx +++ b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx @@ -45,7 +45,10 @@ const useStyles = makeStyles( }, ); -/** @public */ +/** + * Renders search bar for filtering the entity list. + * @public + */ export const EntitySearchBar = () => { const classes = useStyles(); diff --git a/plugins/catalog-react/src/components/EntityTable/EntityTable.tsx b/plugins/catalog-react/src/components/EntityTable/EntityTable.tsx index 62c33701b4..879a35ffd0 100644 --- a/plugins/catalog-react/src/components/EntityTable/EntityTable.tsx +++ b/plugins/catalog-react/src/components/EntityTable/EntityTable.tsx @@ -17,7 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core'; import React, { ReactNode } from 'react'; -import * as columnFactories from './columns'; +import { columnFactories } from './columns'; import { componentEntityColumns, systemEntityColumns } from './presets'; import { Table, TableColumn } from '@backstage/core-components'; @@ -48,7 +48,7 @@ const useStyles = makeStyles(theme => ({ * * @public */ -export function EntityTable(props: EntityTableProps) { +export const EntityTable = (props: EntityTableProps) => { const { entities, title, @@ -85,7 +85,7 @@ export function EntityTable(props: EntityTableProps) { data={entities} /> ); -} +}; EntityTable.columns = columnFactories; diff --git a/plugins/catalog-react/src/components/EntityTable/columns.tsx b/plugins/catalog-react/src/components/EntityTable/columns.tsx index f6198fa1dc..d6c3582af6 100644 --- a/plugins/catalog-react/src/components/EntityTable/columns.tsx +++ b/plugins/catalog-react/src/components/EntityTable/columns.tsx @@ -30,150 +30,136 @@ import { } from '../EntityRefLink'; /** @public */ -export function createEntityRefColumn(options: { - defaultKind?: string; -}): TableColumn { - const { defaultKind } = options; - function formatContent(entity: T): string { - return ( - entity.metadata?.title || - formatEntityRefTitle(entity, { - defaultKind, - }) - ); - } - - return { - title: 'Name', - highlight: true, - customFilterAndSearch(filter, entity) { - // TODO: We could implement this more efficiently, like searching over - // each field that is displayed individually (kind, namespace, name). - // but that might confuse the user as it will behave different than a - // simple text search. - // Another alternative would be to cache the values. But writing them - // into the entity feels bad too. - return formatContent(entity).includes(filter); - }, - customSort(entity1, entity2) { - // TODO: We could implement this more efficiently by comparing field by field. - // This has similar issues as above. - return formatContent(entity1).localeCompare(formatContent(entity2)); - }, - render: entity => ( - - ), - }; -} - -/** @public */ -export function createEntityRelationColumn({ - title, - relation, - defaultKind, - filter: entityFilter, -}: { - title: string; - relation: string; - defaultKind?: string; - filter?: { kind: string }; -}): TableColumn { - function getRelations(entity: T): EntityName[] { - return getEntityRelations(entity, relation, entityFilter); - } - - function formatContent(entity: T): string { - return getRelations(entity) - .map(r => formatEntityRefTitle(r, { defaultKind })) - .join(', '); - } - - return { - title, - customFilterAndSearch(filter, entity) { - return formatContent(entity).includes(filter); - }, - customSort(entity1, entity2) { - return formatContent(entity1).localeCompare(formatContent(entity2)); - }, - render: entity => { +export const columnFactories = Object.freeze({ + createEntityRefColumn(options: { + defaultKind?: string; + }): TableColumn { + const { defaultKind } = options; + function formatContent(entity: T): string { return ( - + entity.metadata?.title || + formatEntityRefTitle(entity, { + defaultKind, + }) ); - }, - }; -} + } -/** @public */ -export function createOwnerColumn(): TableColumn { - return createEntityRelationColumn({ - title: 'Owner', - relation: RELATION_OWNED_BY, - defaultKind: 'group', - }); -} + return { + title: 'Name', + highlight: true, + customFilterAndSearch(filter, entity) { + // TODO: We could implement this more efficiently, like searching over + // each field that is displayed individually (kind, namespace, name). + // but that might confuse the user as it will behave different than a + // simple text search. + // Another alternative would be to cache the values. But writing them + // into the entity feels bad too. + return formatContent(entity).includes(filter); + }, + customSort(entity1, entity2) { + // TODO: We could implement this more efficiently by comparing field by field. + // This has similar issues as above. + return formatContent(entity1).localeCompare(formatContent(entity2)); + }, + render: entity => ( + + ), + }; + }, + createEntityRelationColumn({ + title, + relation, + defaultKind, + filter: entityFilter, + }: { + title: string; + relation: string; + defaultKind?: string; + filter?: { kind: string }; + }): TableColumn { + function getRelations(entity: T): EntityName[] { + return getEntityRelations(entity, relation, entityFilter); + } -/** @public */ -export function createDomainColumn(): TableColumn { - return createEntityRelationColumn({ - title: 'Domain', - relation: RELATION_PART_OF, - defaultKind: 'domain', - filter: { - kind: 'domain', - }, - }); -} + function formatContent(entity: T): string { + return getRelations(entity) + .map(r => formatEntityRefTitle(r, { defaultKind })) + .join(', '); + } -/** @public */ -export function createSystemColumn(): TableColumn { - return createEntityRelationColumn({ - title: 'System', - relation: RELATION_PART_OF, - defaultKind: 'system', - filter: { - kind: 'system', - }, - }); -} - -/** @public */ -export function createMetadataDescriptionColumn< - T extends Entity, ->(): TableColumn { - return { - title: 'Description', - field: 'metadata.description', - render: entity => ( - - ), - width: 'auto', - }; -} - -/** @public */ -export function createSpecLifecycleColumn(): TableColumn { - return { - title: 'Lifecycle', - field: 'spec.lifecycle', - }; -} - -/** @public */ -export function createSpecTypeColumn(): TableColumn { - return { - title: 'Type', - field: 'spec.type', - }; -} + return { + title, + customFilterAndSearch(filter, entity) { + return formatContent(entity).includes(filter); + }, + customSort(entity1, entity2) { + return formatContent(entity1).localeCompare(formatContent(entity2)); + }, + render: entity => { + return ( + + ); + }, + }; + }, + createOwnerColumn(): TableColumn { + return this.createEntityRelationColumn({ + title: 'Owner', + relation: RELATION_OWNED_BY, + defaultKind: 'group', + }); + }, + createDomainColumn(): TableColumn { + return this.createEntityRelationColumn({ + title: 'Domain', + relation: RELATION_PART_OF, + defaultKind: 'domain', + filter: { + kind: 'domain', + }, + }); + }, + createSystemColumn(): TableColumn { + return this.createEntityRelationColumn({ + title: 'System', + relation: RELATION_PART_OF, + defaultKind: 'system', + filter: { + kind: 'system', + }, + }); + }, + createMetadataDescriptionColumn(): TableColumn { + return { + title: 'Description', + field: 'metadata.description', + render: entity => ( + + ), + width: 'auto', + }; + }, + createSpecLifecycleColumn(): TableColumn { + return { + title: 'Lifecycle', + field: 'spec.lifecycle', + }; + }, + createSpecTypeColumn(): TableColumn { + return { + title: 'Type', + field: 'spec.type', + }; + }, +}); diff --git a/plugins/catalog-react/src/components/EntityTable/index.ts b/plugins/catalog-react/src/components/EntityTable/index.ts index 2ed07f9823..5fb651fe72 100644 --- a/plugins/catalog-react/src/components/EntityTable/index.ts +++ b/plugins/catalog-react/src/components/EntityTable/index.ts @@ -15,4 +15,5 @@ */ export { EntityTable } from './EntityTable'; +export { columnFactories } from './columns'; export type { EntityTableProps } from './EntityTable'; diff --git a/plugins/catalog-react/src/components/EntityTable/presets.tsx b/plugins/catalog-react/src/components/EntityTable/presets.tsx index 2ddffb0b7a..971ecfed20 100644 --- a/plugins/catalog-react/src/components/EntityTable/presets.tsx +++ b/plugins/catalog-react/src/components/EntityTable/presets.tsx @@ -15,29 +15,22 @@ */ import { ComponentEntity, SystemEntity } from '@backstage/catalog-model'; -import { - createDomainColumn, - createEntityRefColumn, - createMetadataDescriptionColumn, - createOwnerColumn, - createSpecLifecycleColumn, - createSpecTypeColumn, - createSystemColumn, -} from './columns'; +import { columnFactories } from './columns'; + import { TableColumn } from '@backstage/core-components'; export const systemEntityColumns: TableColumn[] = [ - createEntityRefColumn({ defaultKind: 'system' }), - createDomainColumn(), - createOwnerColumn(), - createMetadataDescriptionColumn(), + columnFactories.createEntityRefColumn({ defaultKind: 'system' }), + columnFactories.createDomainColumn(), + columnFactories.createOwnerColumn(), + columnFactories.createMetadataDescriptionColumn(), ]; export const componentEntityColumns: TableColumn[] = [ - createEntityRefColumn({ defaultKind: 'component' }), - createSystemColumn(), - createOwnerColumn(), - createSpecTypeColumn(), - createSpecLifecycleColumn(), - createMetadataDescriptionColumn(), + columnFactories.createEntityRefColumn({ defaultKind: 'component' }), + columnFactories.createSystemColumn(), + columnFactories.createOwnerColumn(), + columnFactories.createSpecTypeColumn(), + columnFactories.createSpecLifecycleColumn(), + columnFactories.createMetadataDescriptionColumn(), ]; diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx index 9ed27bbef8..4623cf5d9e 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.test.tsx @@ -26,6 +26,7 @@ import { EntityKindFilter, EntityTypeFilter } from '../../filters'; import { alertApiRef } from '@backstage/core-plugin-api'; import { ApiProvider } from '@backstage/core-app-api'; import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; +import { GetEntityFacetsResponse } from '@backstage/catalog-client'; const entities: Entity[] = [ { @@ -64,7 +65,14 @@ const apis = TestApiRegistry.from( [ catalogApiRef, { - getEntities: jest.fn().mockResolvedValue({ items: entities }), + getEntityFacets: jest.fn().mockResolvedValue({ + facets: { + 'spec.type': entities.map(e => ({ + value: (e.spec as any).type, + count: 1, + })), + }, + } as GetEntityFacetsResponse), }, ], [ diff --git a/plugins/catalog-react/src/components/FavoriteEntity/FavoriteEntity.tsx b/plugins/catalog-react/src/components/FavoriteEntity/FavoriteEntity.tsx index 730c9a2378..3832a82877 100644 --- a/plugins/catalog-react/src/components/FavoriteEntity/FavoriteEntity.tsx +++ b/plugins/catalog-react/src/components/FavoriteEntity/FavoriteEntity.tsx @@ -21,7 +21,10 @@ import StarBorder from '@material-ui/icons/StarBorder'; import React, { ComponentProps } from 'react'; import { useStarredEntity } from '../../hooks/useStarredEntity'; -type Props = ComponentProps & { entity: Entity }; +/** @public */ +export type FavoriteEntityProps = ComponentProps & { + entity: Entity; +}; const YellowStar = withStyles({ root: { @@ -29,17 +32,20 @@ const YellowStar = withStyles({ }, })(Star); +/** @public */ export const favoriteEntityTooltip = (isStarred: boolean) => isStarred ? 'Remove from favorites' : 'Add to favorites'; +/** @public */ export const favoriteEntityIcon = (isStarred: boolean) => isStarred ? : ; /** * IconButton for showing if a current entity is starred and adding/removing it from the favorite entities * @param props - MaterialUI IconButton props extended by required `entity` prop + * @public */ -export const FavoriteEntity = (props: Props) => { +export const FavoriteEntity = (props: FavoriteEntityProps) => { const { toggleStarredEntity, isStarredEntity } = useStarredEntity( props.entity, ); diff --git a/plugins/catalog-react/src/components/FavoriteEntity/index.ts b/plugins/catalog-react/src/components/FavoriteEntity/index.ts index f731ca7483..a46d04b6c7 100644 --- a/plugins/catalog-react/src/components/FavoriteEntity/index.ts +++ b/plugins/catalog-react/src/components/FavoriteEntity/index.ts @@ -19,3 +19,4 @@ export { favoriteEntityIcon, FavoriteEntity, } from './FavoriteEntity'; +export type { FavoriteEntityProps } from './FavoriteEntity'; diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx index b27bbe3948..bf6c8971b0 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/AncestryPage.tsx @@ -16,7 +16,7 @@ import { Entity, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model'; import { @@ -143,7 +143,7 @@ function CustomNode({ node }: DependencyGraphTypes.RenderNodeProps) { navigate( entityRoute({ kind: node.kind, - namespace: node.metadata.namespace || ENTITY_DEFAULT_NAMESPACE, + namespace: node.metadata.namespace || DEFAULT_NAMESPACE, name: node.metadata.name, }), ); diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/ColocatedPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/ColocatedPage.tsx index 96d3900a59..d5a98f434c 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/ColocatedPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/ColocatedPage.tsx @@ -16,8 +16,8 @@ import { Entity, - LOCATION_ANNOTATION, - ORIGIN_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + ANNOTATION_ORIGIN_LOCATION, stringifyEntityRef, } from '@backstage/catalog-model'; import { Progress, ResponseErrorPanel } from '@backstage/core-components'; @@ -53,8 +53,8 @@ function useColocated(entity: Entity): { } { const catalogApi = useApi(catalogApiRef); const currentEntityRef = stringifyEntityRef(entity); - const location = entity.metadata.annotations?.[LOCATION_ANNOTATION]; - const origin = entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION]; + const location = entity.metadata.annotations?.[ANNOTATION_LOCATION]; + const origin = entity.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION]; const { loading, error, value } = useAsync(async () => { if (!location && !origin) { @@ -63,10 +63,10 @@ function useColocated(entity: Entity): { const response = await catalogApi.getEntities({ filter: [ ...(location - ? [{ [`metadata.annotations.${LOCATION_ANNOTATION}`]: location }] + ? [{ [`metadata.annotations.${ANNOTATION_LOCATION}`]: location }] : []), ...(origin - ? [{ [`metadata.annotations.${ORIGIN_LOCATION_ANNOTATION}`]: origin }] + ? [{ [`metadata.annotations.${ANNOTATION_ORIGIN_LOCATION}`]: origin }] : []), ], }); @@ -128,11 +128,11 @@ function Contents(props: { entity: Entity }) { } const atLocation = colocatedEntities.filter( - e => e.metadata.annotations?.[LOCATION_ANNOTATION] === location, + e => e.metadata.annotations?.[ANNOTATION_LOCATION] === location, ); const atOrigin = colocatedEntities.filter( e => - e.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION] === originLocation, + e.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION] === originLocation, ); return ( diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx index 2b29bba4fd..68cb5f2bdf 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx @@ -19,7 +19,7 @@ jest.mock('./useUnregisterEntityDialogState'); import userEvent from '@testing-library/user-event'; import React from 'react'; import { UnregisterEntityDialog } from './UnregisterEntityDialog'; -import { ORIGIN_LOCATION_ANNOTATION } from '@backstage/catalog-model'; +import { ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { CatalogClient } from '@backstage/catalog-client'; import { catalogApiRef } from '../../api'; import { entityRouteRef } from '../../routes'; @@ -55,7 +55,7 @@ describe('UnregisterEntityDialog', () => { name: 'n', namespace: 'ns', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:http://example.com', + [ANNOTATION_ORIGIN_LOCATION]: 'url:http://example.com', }, }, spec: {}, diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx index 5c267916ea..48aa2f4012 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx @@ -41,13 +41,6 @@ const useStyles = makeStyles({ }, }); -type Props = { - open: boolean; - onConfirm: () => any; - onClose: () => any; - entity: Entity; -}; - const Contents = ({ entity, onConfirm, @@ -248,23 +241,30 @@ const Contents = ({ return Internal error: Unknown state; }; -export const UnregisterEntityDialog = ({ - open, - onConfirm, - onClose, - entity, -}: Props) => ( - - - Are you sure you want to unregister this entity? - - - - - - - - -); +/** @public */ +export type UnregisterEntityDialogProps = { + open: boolean; + onConfirm: () => any; + onClose: () => any; + entity: Entity; +}; + +/** @public */ +export const UnregisterEntityDialog = (props: UnregisterEntityDialogProps) => { + const { open, onConfirm, onClose, entity } = props; + return ( + + + Are you sure you want to unregister this entity? + + + + + + + + + ); +}; diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/index.ts b/plugins/catalog-react/src/components/UnregisterEntityDialog/index.ts index 8fc750e706..66eb6961ae 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/index.ts +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/index.ts @@ -15,3 +15,4 @@ */ export { UnregisterEntityDialog } from './UnregisterEntityDialog'; +export type { UnregisterEntityDialogProps } from './UnregisterEntityDialog'; diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index 8d6083f111..25af7564d1 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -14,12 +14,8 @@ * limitations under the License. */ -import { - Entity, - Location, - ORIGIN_LOCATION_ANNOTATION, -} from '@backstage/catalog-model'; -import { CatalogApi } from '@backstage/catalog-client'; +import { CatalogApi, Location } from '@backstage/catalog-client'; +import { Entity, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; import { act, @@ -43,7 +39,7 @@ function defer(): { promise: Promise; resolve: (value: T) => void } { describe('useUnregisterEntityDialogState', () => { const catalogApiMock = { - getOriginLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getEntities: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), @@ -69,9 +65,7 @@ describe('useUnregisterEntityDialogState', () => { resolveLocation = deferredLocation.resolve; resolveColocatedEntities = deferredColocatedEntities.resolve; - catalogApiMock.getOriginLocationByEntity.mockReturnValue( - deferredLocation.promise, - ); + catalogApiMock.getLocationByRef.mockReturnValue(deferredLocation.promise); catalogApiMock.getEntities.mockReturnValue( deferredColocatedEntities.promise.then(items => ({ items })), ); @@ -83,7 +77,7 @@ describe('useUnregisterEntityDialogState', () => { name: 'n', namespace: 'ns', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:https://example.com', + [ANNOTATION_ORIGIN_LOCATION]: 'url:https://example.com', }, }, spec: {}, @@ -117,7 +111,7 @@ describe('useUnregisterEntityDialogState', () => { }); it('chooses the bootstrap path when necessary', async () => { - entity.metadata.annotations![ORIGIN_LOCATION_ANNOTATION] = + entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION] = 'bootstrap:bootstrap'; let rendered: RenderHookResult; @@ -141,7 +135,7 @@ describe('useUnregisterEntityDialogState', () => { }); it('chooses only-delete when there was no location annotation', async () => { - delete entity.metadata.annotations![ORIGIN_LOCATION_ANNOTATION]; + delete entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION]; let rendered: RenderHookResult; act(() => { diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.ts b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.ts index 7f75016e16..6420ebd5ae 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.ts +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.ts @@ -18,7 +18,7 @@ import { Entity, EntityName, getEntityName, - ORIGIN_LOCATION_ANNOTATION, + ANNOTATION_ORIGIN_LOCATION, } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; import { useCallback } from 'react'; @@ -60,20 +60,20 @@ export function useUnregisterEntityDialogState( entity: Entity, ): UseUnregisterEntityDialogState { const catalogApi = useApi(catalogApiRef); - const locationRef = entity.metadata.annotations?.[ORIGIN_LOCATION_ANNOTATION]; + const locationRef = entity.metadata.annotations?.[ANNOTATION_ORIGIN_LOCATION]; const uid = entity.metadata.uid; const isBootstrap = locationRef === 'bootstrap:bootstrap'; // Load the prerequisite data: what entities that are colocated with us, and // what location that spawned us const prerequisites = useAsync(async () => { - const locationPromise = catalogApi.getOriginLocationByEntity(entity); + const locationPromise = catalogApi.getLocationByRef(locationRef!); let colocatedEntitiesPromise: Promise; if (!locationRef) { colocatedEntitiesPromise = Promise.resolve([]); } else { - const locationAnnotationFilter = `metadata.annotations.${ORIGIN_LOCATION_ANNOTATION}`; + const locationAnnotationFilter = `metadata.annotations.${ANNOTATION_ORIGIN_LOCATION}`; colocatedEntitiesPromise = catalogApi .getEntities({ filter: { [locationAnnotationFilter]: locationRef }, diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index d4cfedecbf..630a995bbe 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -36,6 +36,7 @@ import { identityApiRef, storageApiRef, } from '@backstage/core-plugin-api'; +import { useEntityOwnership } from '../../hooks'; const mockUser: UserEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -81,9 +82,9 @@ jest.mock('../../hooks', () => { const actual = jest.requireActual('../../hooks'); return { ...actual, - useEntityOwnership: () => ({ + useEntityOwnership: jest.fn(() => ({ isOwnedEntity: mockIsOwnedEntity, - }), + })), useStarredEntities: () => ({ isStarredEntity: mockIsStarredEntity, }), @@ -327,6 +328,19 @@ describe('', () => { }); }); + it('does not reset the filter while owned entities are loading', () => { + const isOwnedEntity = jest.fn(() => false); + (useEntityOwnership as jest.Mock).mockReturnValueOnce({ + loading: true, + isOwnedEntity, + }); + + render(picker({ loading: false })); + expect(updateFilters).not.toHaveBeenCalledWith({ + user: new UserListFilter('all', isOwnedEntity, mockIsStarredEntity), + }); + }); + it('resets the filter to "all" when entities are loaded', () => { render(picker({ loading: false })); diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index cbf6089f2e..3019ae32eb 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -118,20 +118,25 @@ function getFilterGroups(orgName: string | undefined): ButtonGroup[] { ]; } -type UserListPickerProps = { +/** @public */ +export type UserListPickerProps = { initialFilter?: UserListFilterKind; availableFilters?: UserListFilterKind[]; }; -export const UserListPicker = ({ - initialFilter, - availableFilters, -}: UserListPickerProps) => { +/** @public */ +export const UserListPicker = (props: UserListPickerProps) => { + const { initialFilter, availableFilters } = props; const classes = useStyles(); const configApi = useApi(configApiRef); const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; - const { filters, updateFilters, backendEntities, queryParameters, loading } = - useEntityListProvider(); + const { + filters, + updateFilters, + backendEntities, + queryParameters, + loading: loadingBackendEntities, + } = useEntityListProvider(); // Remove group items that aren't in availableFilters and exclude // any now-empty groups. @@ -149,7 +154,10 @@ export const UserListPicker = ({ .filter(({ items }) => !!items.length); const { isStarredEntity } = useStarredEntities(); - const { isOwnedEntity } = useEntityOwnership(); + const { isOwnedEntity, loading: loadingEntityOwnership } = + useEntityOwnership(); + + const loading = loadingBackendEntities || loadingEntityOwnership; // Static filters; used for generating counts of potentially unselected kinds const ownedFilter = useMemo( diff --git a/plugins/catalog-react/src/components/UserListPicker/index.ts b/plugins/catalog-react/src/components/UserListPicker/index.ts index 45cb471197..269c4ca304 100644 --- a/plugins/catalog-react/src/components/UserListPicker/index.ts +++ b/plugins/catalog-react/src/components/UserListPicker/index.ts @@ -15,4 +15,5 @@ */ export { UserListPicker } from './UserListPicker'; +export type { UserListPickerProps } from './UserListPicker'; export type { CatalogReactUserListPickerClassKey } from './UserListPicker'; diff --git a/plugins/catalog-react/src/filters.test.ts b/plugins/catalog-react/src/filters.test.ts index 668e3b4bc3..cdc2ce2150 100644 --- a/plugins/catalog-react/src/filters.test.ts +++ b/plugins/catalog-react/src/filters.test.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { Entity, TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { EntityTextFilter } from './filters'; const entities: Entity[] = [ diff --git a/plugins/catalog-react/src/filters.ts b/plugins/catalog-react/src/filters.ts index 2804d5d6bd..5d2c2e531b 100644 --- a/plugins/catalog-react/src/filters.ts +++ b/plugins/catalog-react/src/filters.ts @@ -19,6 +19,10 @@ import { formatEntityRefTitle } from './components/EntityRefLink'; import { EntityFilter, UserListFilterKind } from './types'; import { getEntityRelations } from './utils'; +/** + * Filter entities based on Kind. + * @public + */ export class EntityKindFilter implements EntityFilter { constructor(readonly value: string) {} @@ -31,6 +35,10 @@ export class EntityKindFilter implements EntityFilter { } } +/** + * Filters entities based on type + * @public + */ export class EntityTypeFilter implements EntityFilter { constructor(readonly value: string | string[]) {} @@ -48,6 +56,10 @@ export class EntityTypeFilter implements EntityFilter { } } +/** + * Filters entities based on tag. + * @public + */ export class EntityTagFilter implements EntityFilter { constructor(readonly values: string[]) {} @@ -60,6 +72,10 @@ export class EntityTagFilter implements EntityFilter { } } +/** + * Filters entities where the text matches spec, title or tags. + * @public + */ export class EntityTextFilter implements EntityFilter { constructor(readonly value: string) {} @@ -81,6 +97,10 @@ export class EntityTextFilter implements EntityFilter { } } +/** + * Filter matching entities that are owned by group. + * @public + */ export class EntityOwnerFilter implements EntityFilter { constructor(readonly values: string[]) {} @@ -97,6 +117,10 @@ export class EntityOwnerFilter implements EntityFilter { } } +/** + * Filters entities on lifecycle. + * @public + */ export class EntityLifecycleFilter implements EntityFilter { constructor(readonly values: string[]) {} @@ -109,6 +133,10 @@ export class EntityLifecycleFilter implements EntityFilter { } } +/** + * Filters entities based on whatever the user has starred or owns them. + * @public + */ export class UserListFilter implements EntityFilter { constructor( readonly value: UserListFilterKind, diff --git a/plugins/catalog-react/src/hooks/index.ts b/plugins/catalog-react/src/hooks/index.ts index 06791f5706..ba6a1c7341 100644 --- a/plugins/catalog-react/src/hooks/index.ts +++ b/plugins/catalog-react/src/hooks/index.ts @@ -21,6 +21,7 @@ export { AsyncEntityProvider, } from './useEntity'; export type { + EntityLoadingStatus, EntityProviderProps, AsyncEntityProviderProps, } from './useEntity'; @@ -30,8 +31,12 @@ export { EntityListProvider, useEntityListProvider, } from './useEntityListProvider'; -export type { DefaultEntityFilters } from './useEntityListProvider'; +export type { + DefaultEntityFilters, + EntityListContextProps, +} from './useEntityListProvider'; export { useEntityTypeFilter } from './useEntityTypeFilter'; +export type { EntityTypeReturn } from './useEntityTypeFilter'; export { useEntityKinds } from './useEntityKinds'; export { useOwnUser } from './useOwnUser'; export { useRelatedEntities } from './useRelatedEntities'; diff --git a/plugins/catalog-react/src/hooks/useEntity.tsx b/plugins/catalog-react/src/hooks/useEntity.tsx index 6ad61a5d81..8637b820d4 100644 --- a/plugins/catalog-react/src/hooks/useEntity.tsx +++ b/plugins/catalog-react/src/hooks/useEntity.tsx @@ -32,7 +32,8 @@ import useAsyncRetry from 'react-use/lib/useAsyncRetry'; import { catalogApiRef } from '../api'; import { useEntityCompoundName } from './useEntityCompoundName'; -type EntityLoadingStatus = { +/** @public */ +export type EntityLoadingStatus = { entity?: Entity; loading: boolean; error?: Error; @@ -133,6 +134,7 @@ const CompatibilityProvider = ({ }; EntityContext.Provider = CompatibilityProvider as Provider; +/** @public */ export const useEntityFromUrl = (): EntityLoadingStatus => { const { kind, namespace, name } = useEntityCompoundName(); const navigate = useNavigate(); diff --git a/plugins/catalog-react/src/hooks/useEntityCompoundName.ts b/plugins/catalog-react/src/hooks/useEntityCompoundName.ts index 57e1c08a23..75affc98b2 100644 --- a/plugins/catalog-react/src/hooks/useEntityCompoundName.ts +++ b/plugins/catalog-react/src/hooks/useEntityCompoundName.ts @@ -18,6 +18,7 @@ import { useRouteRefParams } from '@backstage/core-plugin-api'; /** * Grabs entity kind, namespace, and name from the location + * @public */ export const useEntityCompoundName = () => { const { kind, namespace, name } = useRouteRefParams(entityRouteRef); diff --git a/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx index cdcac8c194..c96301b3c4 100644 --- a/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityKinds.test.tsx @@ -16,45 +16,21 @@ import React, { PropsWithChildren } from 'react'; import { CatalogApi } from '@backstage/catalog-client'; -import { Entity } from '@backstage/catalog-model'; import { catalogApiRef } from '../api'; import { renderHook } from '@testing-library/react-hooks'; import { useEntityKinds } from './useEntityKinds'; import { TestApiProvider } from '@backstage/test-utils'; -const entities: Entity[] = [ - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'component-1', - }, - }, - { - apiVersion: '1', - kind: 'Component', - metadata: { - name: 'component-2', - }, - }, - { - apiVersion: '1', - kind: 'Template', - metadata: { - name: 'template', - }, - }, - { - apiVersion: '1', - kind: 'System', - metadata: { - name: 'system', - }, - }, -]; - const mockCatalogApi: Partial = { - getEntities: jest.fn().mockResolvedValue({ items: entities }), + getEntityFacets: jest.fn().mockResolvedValue({ + facets: { + kind: [ + { value: 'Template', count: 2 }, + { value: 'System', count: 1 }, + { value: 'Component', count: 3 }, + ], + }, + }), }; const wrapper = ({ children }: PropsWithChildren<{}>) => { @@ -66,24 +42,10 @@ const wrapper = ({ children }: PropsWithChildren<{}>) => { }; describe('useEntityKinds', () => { - it('does not return duplicate kinds', async () => { + it('gets entity kinds', async () => { const { result, waitForValueToChange } = renderHook( () => useEntityKinds(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current); - expect(result.current.kinds).toBeDefined(); - expect(result.current.kinds!.length).toBe(3); - }); - - it('sorts entity kinds', async () => { - const { result, waitForValueToChange } = renderHook( - () => useEntityKinds(), - { - wrapper, - }, + { wrapper }, ); await waitForValueToChange(() => result.current); expect(result.current.kinds).toEqual(['Component', 'System', 'Template']); diff --git a/plugins/catalog-react/src/hooks/useEntityKinds.ts b/plugins/catalog-react/src/hooks/useEntityKinds.ts index 1d5b2fec52..5fad49df8e 100644 --- a/plugins/catalog-react/src/hooks/useEntityKinds.ts +++ b/plugins/catalog-react/src/hooks/useEntityKinds.ts @@ -18,7 +18,10 @@ import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '../api'; -// Retrieve a list of unique entity kinds present in the catalog +/** + * Retrieve a list of unique entity kinds present in the catalog + * @public + */ export function useEntityKinds() { const catalogApi = useApi(catalogApiRef); @@ -27,11 +30,9 @@ export function useEntityKinds() { loading, value: kinds, } = useAsync(async () => { - const entities = await catalogApi - .getEntities({ fields: ['kind'] }) - .then(response => response.items); - - return [...new Set(entities.map(e => e.kind))].sort(); + return await catalogApi + .getEntityFacets({ facets: ['kind'] }) + .then(response => response.facets.kind?.map(f => f.value).sort() || []); }); return { error, loading, kinds }; } diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index 9b4d850208..d6c4e3749a 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -43,6 +43,7 @@ import { EntityFilter } from '../types'; import { reduceCatalogFilters, reduceEntityFilters } from '../utils'; import { useApi } from '@backstage/core-plugin-api'; +/** @public */ export type DefaultEntityFilters = { kind?: EntityKindFilter; type?: EntityTypeFilter; @@ -53,6 +54,7 @@ export type DefaultEntityFilters = { text?: EntityTextFilter; }; +/** @public */ export type EntityListContextProps< EntityFilters extends DefaultEntityFilters = DefaultEntityFilters, > = { @@ -91,6 +93,10 @@ export type EntityListContextProps< error?: Error; }; +/** + * Creates new context for entity listing and filtering. + * @public + */ export const EntityListContext = createContext< EntityListContextProps | undefined >(undefined); @@ -101,6 +107,10 @@ type OutputState = { backendEntities: Entity[]; }; +/** + * Provides entities and filters for a catalog listing. + * @public + */ export const EntityListProvider = ({ children, }: PropsWithChildren<{}>) => { @@ -239,6 +249,10 @@ export const EntityListProvider = ({ ); }; +/** + * Hook for interacting with the entity list context provided by the {@link EntityListProvider}. + * @public + */ export function useEntityListProvider< EntityFilters extends DefaultEntityFilters = DefaultEntityFilters, >(): EntityListContextProps { diff --git a/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx b/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx index c4531d9117..cfe821b4f7 100644 --- a/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx +++ b/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx @@ -17,12 +17,14 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import isEqual from 'lodash/isEqual'; +import sortBy from 'lodash/sortBy'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '../api'; import { useEntityListProvider } from './useEntityListProvider'; import { EntityTypeFilter } from '../filters'; -type EntityTypeReturn = { +/** @public */ +export type EntityTypeReturn = { loading: boolean; error?: Error; availableTypes: string[]; @@ -33,6 +35,7 @@ type EntityTypeReturn = { /** * A hook built on top of `useEntityListProvider` for enabling selection of valid `spec.type` values * based on the selected EntityKindFilter. + * @public */ export function useEntityTypeFilter(): EntityTypeReturn { const catalogApi = useApi(catalogApiRef); @@ -67,51 +70,34 @@ export function useEntityTypeFilter(): EntityTypeReturn { const { error, loading, - value: entities, + value: facets, } = useAsync(async () => { if (kind) { const items = await catalogApi - .getEntities({ + .getEntityFacets({ filter: { kind }, - fields: ['spec.type'], + facets: ['spec.type'], }) - .then(response => response.items); + .then(response => response.facets['spec.type'] || []); return items; } return []; }, [kind, catalogApi]); - const entitiesRef = useRef(entities); + const facetsRef = useRef(facets); useEffect(() => { - const oldEntities = entitiesRef.current; - entitiesRef.current = entities; - // Delay processing hook until kind and entity load updates have settled to generate list of types; - // This prevents reseting the type filter due to saved type value from query params not matching the + const oldFacets = facetsRef.current; + facetsRef.current = facets; + // Delay processing hook until kind and facets load updates have settled to generate list of types; + // This prevents resetting the type filter due to saved type value from query params not matching the // empty set of type values while values are still being loaded; also only run this hook on changes - // to entities - if (loading || !kind || oldEntities === entities) { + // to facets + if (loading || !kind || oldFacets === facets || !facets) { return; } - // Resolve the unique set of types from returned entities; could be optimized by a new endpoint - // in the catalog-backend that does this, rather than loading entities with redundant types. - if (!entities) return; - - // Sort by entity count descending, so the most common types appear on top - const countByType = entities.reduce((acc, entity) => { - if (typeof entity.spec?.type !== 'string') return acc; - - const entityType = entity.spec.type.toLocaleLowerCase('en-US'); - if (!acc[entityType]) { - acc[entityType] = 0; - } - acc[entityType] += 1; - return acc; - }, {} as Record); - - const newTypes = Object.entries(countByType) - .sort(([, count1], [, count2]) => count2 - count1) - .map(([type]) => type); + // Sort by facet count descending, so the most common types appear on top + const newTypes = sortBy(facets, f => -f.count).map(f => f.value); setAvailableTypes(newTypes); // Update type filter to only valid values when the list of available types has changed @@ -121,7 +107,7 @@ export function useEntityTypeFilter(): EntityTypeReturn { if (!isEqual(selectedTypes, stillValidTypes)) { setSelectedTypes(stillValidTypes); } - }, [loading, kind, selectedTypes, setSelectedTypes, entities]); + }, [loading, kind, selectedTypes, setSelectedTypes, facets]); useEffect(() => { updateFilters({ diff --git a/plugins/catalog-react/src/hooks/useOwnUser.ts b/plugins/catalog-react/src/hooks/useOwnUser.ts index f49eb768d0..1477de67aa 100644 --- a/plugins/catalog-react/src/hooks/useOwnUser.ts +++ b/plugins/catalog-react/src/hooks/useOwnUser.ts @@ -15,7 +15,7 @@ */ import { - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, parseEntityRef, UserEntity, } from '@backstage/catalog-model'; @@ -25,6 +25,7 @@ import { identityApiRef, useApi } from '@backstage/core-plugin-api'; /** * Get the catalog User entity (if any) that matches the logged-in user. + * @public */ export function useOwnUser(): AsyncState { const catalogApi = useApi(catalogApiRef); @@ -35,7 +36,7 @@ export function useOwnUser(): AsyncState { return catalogApi.getEntityByName( parseEntityRef(identity.userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }), ) as Promise; }, [catalogApi, identityApi]); diff --git a/plugins/catalog-react/src/hooks/useOwnedEntities.ts b/plugins/catalog-react/src/hooks/useOwnedEntities.ts index ffe64830f4..dad73740c1 100644 --- a/plugins/catalog-react/src/hooks/useOwnedEntities.ts +++ b/plugins/catalog-react/src/hooks/useOwnedEntities.ts @@ -19,8 +19,8 @@ import { loadIdentityOwnerRefs, } from './useEntityOwnership'; import { identityApiRef, useApi } from '@backstage/core-plugin-api'; -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { CatalogListResponse } from '@backstage/catalog-client'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; import useAsync from 'react-use/lib/useAsync'; import { useMemo } from 'react'; @@ -32,11 +32,10 @@ import { useMemo } from 'react'; * @public * * @param allowedKinds - Array of allowed kinds to filter the entities - * @returns CatalogListResponse */ export function useOwnedEntities(allowedKinds?: string[]): { loading: boolean; - ownedEntities: CatalogListResponse | undefined; + ownedEntities: GetEntitiesResponse | undefined; } { const identityApi = useApi(identityApiRef); const catalogApi = useApi(catalogApiRef); diff --git a/plugins/catalog-react/src/hooks/useRelatedEntities.ts b/plugins/catalog-react/src/hooks/useRelatedEntities.ts index 942941e3d5..56dfbe6403 100644 --- a/plugins/catalog-react/src/hooks/useRelatedEntities.ts +++ b/plugins/catalog-react/src/hooks/useRelatedEntities.ts @@ -21,6 +21,7 @@ import { catalogApiRef } from '../api'; const BATCH_SIZE = 20; +/** @public */ export function useRelatedEntities( entity: Entity, { type, kind }: { type?: string; kind?: string }, diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.ts b/plugins/catalog-react/src/hooks/useStarredEntities.ts index 066040bf02..5ddabfdd2e 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.ts +++ b/plugins/catalog-react/src/hooks/useStarredEntities.ts @@ -30,6 +30,7 @@ function getEntityRef(entityOrRef: Entity | EntityName | string): string { : stringifyEntityRef(entityOrRef); } +/** @public */ export function useStarredEntities(): { starredEntities: Set; toggleStarredEntity: (entityOrRef: Entity | EntityName | string) => void; diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.ts b/plugins/catalog-react/src/hooks/useStarredEntity.ts index 0233432196..2c647163aa 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.ts +++ b/plugins/catalog-react/src/hooks/useStarredEntity.ts @@ -29,6 +29,7 @@ function getEntityRef(entityOrRef: Entity | EntityName | string): string { : stringifyEntityRef(entityOrRef); } +/** @public */ export function useStarredEntity(entityOrRef: Entity | EntityName | string): { toggleStarredEntity: () => void; isStarredEntity: boolean; diff --git a/plugins/catalog-react/src/routes.ts b/plugins/catalog-react/src/routes.ts index 1fcbd14866..b9aa0de531 100644 --- a/plugins/catalog-react/src/routes.ts +++ b/plugins/catalog-react/src/routes.ts @@ -14,13 +14,14 @@ * limitations under the License. */ -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { createRouteRef } from '@backstage/core-plugin-api'; import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; // TODO(Rugvip): Move these route refs back to the catalog plugin once we're all ported to using external routes /** * @deprecated Use an `ExternalRouteRef` instead, which can point to `catalogPlugin.routes.catalogIndex`. + * @public */ export const rootRoute = createRouteRef({ id: 'catalog', @@ -28,6 +29,7 @@ export const rootRoute = createRouteRef({ /** * @deprecated Use an `ExternalRouteRef` instead, which can point to `catalogPlugin.routes.catalogIndex`. + * @public */ export const catalogRouteRef = rootRoute; @@ -39,6 +41,7 @@ export const catalogRouteRef = rootRoute; * * If you want to replace the `EntityPage` from `@backstage/catalog-plugin` in your app, * you need to use the `entityRouteRef` as the mount point instead of your own. + * @public */ export const entityRouteRef = getOrCreateGlobalSingleton( 'catalog:entity-route-ref', @@ -51,17 +54,20 @@ export const entityRouteRef = getOrCreateGlobalSingleton( /** * @deprecated use `entityRouteRef` instead. + * @public */ export const entityRoute = entityRouteRef; -// Utility function to get suitable route params for entityRoute, given an -// entity instance +/** + * Utility function to get suitable route params for entityRoute, given an + * @public + */ export function entityRouteParams(entity: Entity) { return { kind: entity.kind.toLocaleLowerCase('en-US'), namespace: entity.metadata.namespace?.toLocaleLowerCase('en-US') ?? - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, name: entity.metadata.name, } as const; } diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/providers.tsx index 3fb295298c..5867026a8c 100644 --- a/plugins/catalog-react/src/testUtils/providers.tsx +++ b/plugins/catalog-react/src/testUtils/providers.tsx @@ -26,6 +26,7 @@ import { EntityListContextProps, } from '../hooks/useEntityListProvider'; +/** @public */ export const MockEntityListContextProvider = ({ children, value, diff --git a/plugins/catalog-react/src/types.ts b/plugins/catalog-react/src/types.ts index 964858cb10..440bab2b22 100644 --- a/plugins/catalog-react/src/types.ts +++ b/plugins/catalog-react/src/types.ts @@ -16,6 +16,7 @@ import { Entity } from '@backstage/catalog-model'; +/** @public */ export type EntityFilter = { /** * Get filters to add to the catalog-backend request. These are a dot-delimited field with @@ -43,4 +44,5 @@ export type EntityFilter = { toQueryValue?: () => string | string[]; }; +/** @public */ export type UserListFilterKind = 'owned' | 'starred' | 'all'; diff --git a/plugins/catalog-react/src/utils/filters.ts b/plugins/catalog-react/src/utils/filters.ts index 109e864c52..d64a821df7 100644 --- a/plugins/catalog-react/src/utils/filters.ts +++ b/plugins/catalog-react/src/utils/filters.ts @@ -17,6 +17,7 @@ import { Entity } from '@backstage/catalog-model'; import { EntityFilter } from '../types'; +/** @public */ export function reduceCatalogFilters( filters: EntityFilter[], ): Record { @@ -28,6 +29,7 @@ export function reduceCatalogFilters( }, {} as Record); } +/** @public */ export function reduceEntityFilters( filters: EntityFilter[], ): (entity: Entity) => boolean { diff --git a/plugins/catalog-react/src/utils/getEntityMetadataUrl.ts b/plugins/catalog-react/src/utils/getEntityMetadataUrl.ts index 996f928ecf..a5cef7d71e 100644 --- a/plugins/catalog-react/src/utils/getEntityMetadataUrl.ts +++ b/plugins/catalog-react/src/utils/getEntityMetadataUrl.ts @@ -15,15 +15,17 @@ */ import { - EDIT_URL_ANNOTATION, + ANNOTATION_EDIT_URL, + ANNOTATION_VIEW_URL, Entity, - VIEW_URL_ANNOTATION, } from '@backstage/catalog-model'; +/** @public */ export function getEntityMetadataViewUrl(entity: Entity): string | undefined { - return entity.metadata.annotations?.[VIEW_URL_ANNOTATION]; + return entity.metadata.annotations?.[ANNOTATION_VIEW_URL]; } +/** @public */ export function getEntityMetadataEditUrl(entity: Entity): string | undefined { - return entity.metadata.annotations?.[EDIT_URL_ANNOTATION]; + return entity.metadata.annotations?.[ANNOTATION_EDIT_URL]; } diff --git a/plugins/catalog-react/src/utils/getEntityRelations.ts b/plugins/catalog-react/src/utils/getEntityRelations.ts index 0045fac4f5..25666a9960 100644 --- a/plugins/catalog-react/src/utils/getEntityRelations.ts +++ b/plugins/catalog-react/src/utils/getEntityRelations.ts @@ -18,6 +18,7 @@ import { Entity, EntityName } from '@backstage/catalog-model'; /** * Get the related entity references. + * @public */ export function getEntityRelations( entity: Entity | undefined, diff --git a/plugins/catalog-react/src/utils/getEntitySourceLocation.ts b/plugins/catalog-react/src/utils/getEntitySourceLocation.ts index 59c3b5ab95..d2141449a8 100644 --- a/plugins/catalog-react/src/utils/getEntitySourceLocation.ts +++ b/plugins/catalog-react/src/utils/getEntitySourceLocation.ts @@ -15,30 +15,32 @@ */ import { + ANNOTATION_SOURCE_LOCATION, Entity, - parseLocationReference, - SOURCE_LOCATION_ANNOTATION, + parseLocationRef, } from '@backstage/catalog-model'; import { ScmIntegrationRegistry } from '@backstage/integration'; +/** @public */ export type EntitySourceLocation = { locationTargetUrl: string; integrationType?: string; }; +/** @public */ export function getEntitySourceLocation( entity: Entity, scmIntegrationsApi: ScmIntegrationRegistry, ): EntitySourceLocation | undefined { const sourceLocation = - entity.metadata.annotations?.[SOURCE_LOCATION_ANNOTATION]; + entity.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION]; if (!sourceLocation) { return undefined; } try { - const sourceLocationRef = parseLocationReference(sourceLocation); + const sourceLocationRef = parseLocationRef(sourceLocation); const integration = scmIntegrationsApi.byUrl(sourceLocationRef.target); return { locationTargetUrl: sourceLocationRef.target, diff --git a/plugins/catalog-react/src/utils/isOwnerOf.ts b/plugins/catalog-react/src/utils/isOwnerOf.ts index 38ad90e4a6..3ef6b4b2a0 100644 --- a/plugins/catalog-react/src/utils/isOwnerOf.ts +++ b/plugins/catalog-react/src/utils/isOwnerOf.ts @@ -25,6 +25,7 @@ import { getEntityRelations } from './getEntityRelations'; /** * Get the related entity references. + * @public */ export function isOwnerOf(owner: Entity, owned: Entity) { const possibleOwners = new Set( diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index cb13e27bd0..aa0e102ab9 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog +## 0.8.0 + +### Minor Changes + +- ae7edbea45: Removed `CatalogClientWrapper` as usage have been replaced by the `fetchApiRef`. +- 37092662cb: **BREAKING** Completely removed the `EntitySystemDiagramCard` component which was deprecated in a previous release. Any remaining references to this component are now broken and should be replaced with `EntityCatalogGraphCard`, which can be imported from package `@backstage/plugin-catalog-graph`. +- 7657eeae22: Removed deprecated `Router` and `EntityPageLayout` exports. + `Router` is replaced by plugin extensions and `EntityPageLayout` is replaced by `CatalogEntityPage`. +- 0a033351be: **BREAKING**: + + - The `CatalogResultListItem` `result` prop is now of the more narrow and correct type `IndexableDocument`, rather than `any`. + - The individual table column factories (e.g. `createNameColumn`) are now no longer available directly, but only through `CatalogTable.columns`. + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- 0d03e42a89: Replaced use of deprecated `compareEntityToRef` utility. +- 244d24ebc4: Import `Location` from the `@backstage/catalog-client` package. +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 27eccab216: Replaces use of deprecated catalog-model constants. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/search-common@0.2.3 + - @backstage/theme@0.2.15 + - @backstage/plugin-catalog-common@0.1.3 + ## 0.7.12 ### Patch Changes diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index e7825127a6..053a46bc35 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -5,26 +5,15 @@ ```ts /// -import { AddLocationRequest } from '@backstage/catalog-client'; -import { AddLocationResponse } from '@backstage/catalog-client'; import { ApiHolder } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { CatalogApi } from '@backstage/catalog-client'; -import { CatalogClient } from '@backstage/catalog-client'; -import { CatalogEntitiesRequest } from '@backstage/catalog-client'; -import { CatalogEntityAncestorsRequest } from '@backstage/catalog-client'; -import { CatalogEntityAncestorsResponse } from '@backstage/catalog-client'; -import { CatalogListResponse } from '@backstage/catalog-client'; -import { CatalogRequestOptions } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { EntityName } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; -import { IdentityApi } from '@backstage/core-plugin-api'; +import { IndexableDocument } from '@backstage/search-common'; import { InfoCardVariants } from '@backstage/core-components'; -import { Location as Location_2 } from '@backstage/catalog-model'; import { Overrides } from '@material-ui/core/styles/overrides'; -import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -34,28 +23,38 @@ import { TableProps } from '@backstage/core-components'; import { TabProps } from '@material-ui/core'; import { UserListFilterKind } from '@backstage/plugin-catalog-react'; -// Warning: (ae-forgotten-export) The symbol "AboutCardProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "AboutCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function AboutCard({ variant }: AboutCardProps): JSX.Element; +// @public @deprecated (undocumented) +export function AboutCard(props: AboutCardProps): JSX.Element; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "AboutContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const AboutContent: ({ entity }: Props) => JSX.Element; +// @public +export interface AboutCardProps { + // (undocumented) + variant?: InfoCardVariants; +} -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "AboutField" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const AboutField: ({ - label, - value, - gridSizes, - children, -}: Props_2) => JSX.Element; +export function AboutContent(props: AboutContentProps): JSX.Element; + +// @public +export interface AboutContentProps { + // (undocumented) + entity: Entity; +} + +// @public (undocumented) +export function AboutField(props: AboutFieldProps): JSX.Element; + +// @public +export interface AboutFieldProps { + // (undocumented) + children?: React_2.ReactNode; + // (undocumented) + gridSizes?: Record; + // (undocumented) + label: string; + // (undocumented) + value?: string; +} // @public (undocumented) export type BackstageOverrides = Overrides & { @@ -64,85 +63,23 @@ export type BackstageOverrides = Overrides & { >; }; -// Warning: (ae-missing-release-tag) "CatalogClientWrapper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated -export class CatalogClientWrapper implements CatalogApi { - constructor(options: { client: CatalogClient; identityApi: IdentityApi }); - // (undocumented) - addLocation( - request: AddLocationRequest, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - getEntities( - request?: CatalogEntitiesRequest, - options?: CatalogRequestOptions, - ): Promise>; - // (undocumented) - getEntityAncestors( - request: CatalogEntityAncestorsRequest, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - getEntityByName( - compoundName: EntityName, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - getLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - getLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - getOriginLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - refreshEntity( - entityRef: string, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - removeEntityByUid( - uid: string, - options?: CatalogRequestOptions, - ): Promise; - // (undocumented) - removeLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise; -} - -// Warning: (ae-missing-release-tag) "CatalogEntityPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const CatalogEntityPage: () => JSX.Element; -// Warning: (ae-missing-release-tag) "CatalogIndexPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const CatalogIndexPage: (props: DefaultCatalogPageProps) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "CatalogKindHeaderProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "CatalogKindHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const CatalogKindHeader: ({ - initialFilter, -}: CatalogKindHeaderProps) => JSX.Element; +export function CatalogKindHeader(props: CatalogKindHeaderProps): JSX.Element; + +// @public +export interface CatalogKindHeaderProps { + // (undocumented) + initialFilter?: string; +} -// Warning: (ae-missing-release-tag) "catalogPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -const catalogPlugin: BackstagePlugin< +export const catalogPlugin: BackstagePlugin< { catalogIndex: RouteRef; catalogEntity: RouteRef<{ @@ -163,27 +100,57 @@ const catalogPlugin: BackstagePlugin< >; } >; -export { catalogPlugin }; -export { catalogPlugin as plugin }; -// Warning: (ae-missing-release-tag) "CatalogResultListItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public @deprecated (undocumented) +export const CatalogResultListItem: typeof CatalogSearchResultListItem; + +// @public @deprecated (undocumented) +export type CatalogResultListItemProps = CatalogSearchResultListItemProps; + // @public (undocumented) -export const CatalogResultListItem: ({ result }: any) => JSX.Element; +export function CatalogSearchResultListItem( + props: CatalogSearchResultListItemProps, +): JSX.Element; + +// @public +export interface CatalogSearchResultListItemProps { + // (undocumented) + result: IndexableDocument; +} -// Warning: (ae-missing-release-tag) "CatalogTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const CatalogTable: { - ({ columns, actions }: CatalogTableProps): JSX.Element; - columns: typeof columnFactories; + (props: CatalogTableProps): JSX.Element; + columns: Readonly<{ + createNameColumn( + options?: + | { + defaultKind?: string | undefined; + } + | undefined, + ): TableColumn; + createSystemColumn(): TableColumn; + createOwnerColumn(): TableColumn; + createSpecTypeColumn(): TableColumn; + createSpecLifecycleColumn(): TableColumn; + createMetadataDescriptionColumn(): TableColumn; + createTagsColumn(): TableColumn; + }>; }; -// Warning: (ae-missing-release-tag) "EntityRow" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @public +export interface CatalogTableProps { + // (undocumented) + actions?: TableProps['actions']; + // (undocumented) + columns?: TableColumn[]; +} + // @public (undocumented) -export type CatalogTableRow = { +export interface CatalogTableRow { + // (undocumented) entity: Entity; + // (undocumented) resolved: { name: string; partOfSystemRelationTitle?: string; @@ -191,252 +158,234 @@ export type CatalogTableRow = { ownedByRelationsTitle?: string; ownedByRelations: EntityName[]; }; -}; +} -// Warning: (ae-missing-release-tag) "createMetadataDescriptionColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export function createMetadataDescriptionColumn(): TableColumn; - -// Warning: (ae-forgotten-export) The symbol "NameColumnProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "createNameColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createNameColumn( - props?: NameColumnProps, -): TableColumn; - -// Warning: (ae-missing-release-tag) "createOwnerColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createOwnerColumn(): TableColumn; - -// Warning: (ae-missing-release-tag) "createSpecLifecycleColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createSpecLifecycleColumn(): TableColumn; - -// Warning: (ae-missing-release-tag) "createSpecTypeColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createSpecTypeColumn(): TableColumn; - -// Warning: (ae-missing-release-tag) "createSystemColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createSystemColumn(): TableColumn; - -// Warning: (ae-missing-release-tag) "createTagsColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function createTagsColumn(): TableColumn; +export const columnFactories: Readonly<{ + createNameColumn( + options?: + | { + defaultKind?: string | undefined; + } + | undefined, + ): TableColumn; + createSystemColumn(): TableColumn; + createOwnerColumn(): TableColumn; + createSpecTypeColumn(): TableColumn; + createSpecLifecycleColumn(): TableColumn; + createMetadataDescriptionColumn(): TableColumn; + createTagsColumn(): TableColumn; +}>; // @public -export type DefaultCatalogPageProps = { - initiallySelectedFilter?: UserListFilterKind; - columns?: TableColumn[]; +export interface DefaultCatalogPageProps { + // (undocumented) actions?: TableProps['actions']; -}; + // (undocumented) + columns?: TableColumn[]; + // (undocumented) + initiallySelectedFilter?: UserListFilterKind; +} -// Warning: (ae-missing-release-tag) "EntityAboutCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityAboutCard: AboutCard; +export interface DependencyOfComponentsCardProps { + // (undocumented) + title?: string; + // (undocumented) + variant?: 'gridItem'; +} -// Warning: (ae-missing-release-tag) "EntityDependencyOfComponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityDependencyOfComponentsCard: ({ - variant, - title, -}: { - variant?: 'gridItem' | undefined; - title?: string | undefined; -}) => JSX.Element; +export interface DependsOnComponentsCardProps { + // (undocumented) + title?: string; + // (undocumented) + variant?: 'gridItem'; +} -// Warning: (ae-missing-release-tag) "EntityDependsOnComponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityDependsOnComponentsCard: ({ - variant, - title, -}: { - variant?: 'gridItem' | undefined; - title?: string | undefined; -}) => JSX.Element; +export interface DependsOnResourcesCardProps { + // (undocumented) + variant?: 'gridItem'; +} -// Warning: (ae-missing-release-tag) "EntityDependsOnResourcesCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityDependsOnResourcesCard: ({ - variant, -}: { - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityAboutCard: (props: AboutCardProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityHasComponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityHasComponentsCard: ({ - variant, -}: { - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityDependencyOfComponentsCard: ( + props: DependencyOfComponentsCardProps, +) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityHasResourcesCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityHasResourcesCard: ({ - variant, -}: { - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityDependsOnComponentsCard: ( + props: DependsOnComponentsCardProps, +) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityHasSubcomponentsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityHasSubcomponentsCard: ({ - variant, -}: { - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityDependsOnResourcesCard: ( + props: DependsOnResourcesCardProps, +) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityHasSystemsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityHasSystemsCard: ({ - variant, -}: { - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityHasComponentsCard: ( + props: HasComponentsCardProps, +) => JSX.Element; + +// @public (undocumented) +export const EntityHasResourcesCard: ( + props: HasResourcesCardProps, +) => JSX.Element; + +// @public (undocumented) +export const EntityHasSubcomponentsCard: ( + props: HasSubcomponentsCardProps, +) => JSX.Element; + +// @public (undocumented) +export const EntityHasSystemsCard: (props: HasSystemsCardProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "EntityLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public export const EntityLayout: { - ({ - UNSTABLE_extraContextMenuItems, - UNSTABLE_contextMenuOptions, - children, - }: EntityLayoutProps): JSX.Element; - Route: (props: SubRoute) => null; + (props: EntityLayoutProps): JSX.Element; + Route: (props: EntityLayoutRouteProps) => null; }; -// Warning: (ae-missing-release-tag) "EntityLinksCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// @public (undocumented) +export interface EntityLayoutProps { + // (undocumented) + children?: React_2.ReactNode; + // Warning: (ae-forgotten-export) The symbol "contextMenuOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + UNSTABLE_contextMenuOptions?: contextMenuOptions; + // Warning: (ae-forgotten-export) The symbol "ExtraContextMenuItem" needs to be exported by the entry point index.d.ts + // + // (undocumented) + UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; +} + +// @public (undocumented) +export type EntityLayoutRouteProps = { + path: string; + title: string; + children: JSX.Element; + if?: (entity: Entity) => boolean; + tabProps?: TabProps< + React_2.ElementType, + { + component?: React_2.ElementType; + } + >; +}; + +// Warning: (ae-forgotten-export) The symbol "EntityLinksCard" needs to be exported by the entry point index.d.ts // // @public (undocumented) -export const EntityLinksCard: ({ - cols, - variant, -}: { - entity?: Entity | undefined; - cols?: number | ColumnBreakpoints | undefined; - variant?: 'gridItem' | undefined; -}) => JSX.Element; +export const EntityLinksCard: EntityLinksCard_2; + +// @public (undocumented) +export interface EntityLinksCardProps { + // Warning: (ae-forgotten-export) The symbol "ColumnBreakpoints" needs to be exported by the entry point index.d.ts + // + // (undocumented) + cols?: ColumnBreakpoints | number; + // (undocumented) + variant?: 'gridItem'; +} // @public (undocumented) export type EntityLinksEmptyStateClassKey = 'code'; -// Warning: (ae-missing-release-tag) "EntityListContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const EntityListContainer: ({ - children, -}: PropsWithChildren<{}>) => JSX.Element; +export function EntityListContainer(props: { + children: React_2.ReactNode; +}): JSX.Element; -// Warning: (ae-missing-release-tag) "EntityOrphanWarning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public -export const EntityOrphanWarning: () => JSX.Element; +export function EntityOrphanWarning(): JSX.Element; -// Warning: (ae-missing-release-tag) "EntityPageLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated -export const EntityPageLayout: { - ({ - children, - UNSTABLE_extraContextMenuItems, - UNSTABLE_contextMenuOptions, - }: EntityPageLayoutProps): JSX.Element; - Content: (_props: { - path: string; - title: string; - element: JSX.Element; - }) => null; -}; - -// Warning: (ae-missing-release-tag) "EntityProcessingErrorsPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public -export const EntityProcessingErrorsPanel: () => JSX.Element | null; +export function EntityProcessingErrorsPanel(): JSX.Element | null; -// Warning: (ae-missing-release-tag) "EntitySwitch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const EntitySwitch: { - ({ children }: PropsWithChildren<{}>): JSX.Element | null; - Case: (_: { - if?: - | (( - entity: Entity, - context: { - apis: ApiHolder; - }, - ) => boolean | Promise) - | undefined; - children: ReactNode; - }) => null; + (props: EntitySwitchProps): JSX.Element | null; + Case: (_props: EntitySwitchCaseProps) => null; }; -// Warning: (ae-forgotten-export) The symbol "SystemDiagramCard" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "EntitySystemDiagramCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export const EntitySystemDiagramCard: SystemDiagramCard; - -// Warning: (ae-missing-release-tag) "FilterContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const FilterContainer: ({ - children, -}: PropsWithChildren<{}>) => JSX.Element; +export interface EntitySwitchCaseProps { + // (undocumented) + children: ReactNode; + // (undocumented) + if?: ( + entity: Entity, + context: { + apis: ApiHolder; + }, + ) => boolean | Promise; +} -// Warning: (ae-missing-release-tag) "FilteredEntityLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const FilteredEntityLayout: ({ - children, -}: PropsWithChildren<{}>) => JSX.Element; +// @public +export interface EntitySwitchProps { + // (undocumented) + children: ReactNode; +} -// Warning: (ae-missing-release-tag) "hasCatalogProcessingErrors" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const hasCatalogProcessingErrors: ( +export function FilterContainer(props: { + children: React_2.ReactNode; +}): JSX.Element; + +// @public (undocumented) +export function FilteredEntityLayout(props: { + children: React_2.ReactNode; +}): JSX.Element; + +// @public +export function hasCatalogProcessingErrors( entity: Entity, context: { apis: ApiHolder; }, -) => Promise; +): Promise; -// Warning: (ae-missing-release-tag) "isComponentType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) +export interface HasComponentsCardProps { + // (undocumented) + variant?: 'gridItem'; +} + +// @public (undocumented) +export interface HasResourcesCardProps { + // (undocumented) + variant?: 'gridItem'; +} + +// @public (undocumented) +export interface HasSubcomponentsCardProps { + // (undocumented) + variant?: 'gridItem'; +} + +// @public (undocumented) +export interface HasSystemsCardProps { + // (undocumented) + variant?: 'gridItem'; +} + +// @public export function isComponentType(type: string): (entity: Entity) => boolean; -// Warning: (ae-missing-release-tag) "isKind" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function isKind(kind: string): (entity: Entity) => boolean; -// Warning: (ae-missing-release-tag) "isNamespace" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export function isNamespace(namespace: string): (entity: Entity) => boolean; -// Warning: (ae-missing-release-tag) "isOrphan" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const isOrphan: (entity: Entity) => boolean; +// @public +export function isOrphan(entity: Entity): boolean; // @public (undocumented) export type PluginCatalogComponentsNameToClassKey = { @@ -444,28 +393,22 @@ export type PluginCatalogComponentsNameToClassKey = { PluginCatalogSystemDiagramCard: SystemDiagramCardClassKey; }; -// Warning: (ae-missing-release-tag) "RelatedEntitiesCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) -export const RelatedEntitiesCard: (props: { - variant?: 'gridItem' | undefined; +export const RelatedEntitiesCard: ( + props: RelatedEntitiesCardProps, +) => JSX.Element; + +// @public (undocumented) +export type RelatedEntitiesCardProps = { + variant?: 'gridItem'; title: string; columns: TableColumn[]; - entityKind?: string | undefined; + entityKind?: string; relationType: string; emptyMessage: string; emptyHelpLink: string; asRenderableEntities: (entities: Entity[]) => T[]; -}) => JSX.Element; - -// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public @deprecated (undocumented) -export const Router: ({ - EntityPage, -}: { - EntityPage?: React_2.ComponentType<{}> | undefined; -}) => JSX.Element; +}; // @public (undocumented) export type SystemDiagramCardClassKey = @@ -474,13 +417,4 @@ export type SystemDiagramCardClassKey = | 'componentNode' | 'apiNode' | 'resourceNode'; - -// Warnings were encountered during analysis: -// -// src/components/CatalogTable/CatalogTable.d.ts:10:5 - (ae-forgotten-export) The symbol "CatalogTableProps" needs to be exported by the entry point index.d.ts -// src/components/CatalogTable/CatalogTable.d.ts:11:5 - (ae-forgotten-export) The symbol "columnFactories" needs to be exported by the entry point index.d.ts -// src/components/EntityLayout/EntityLayout.d.ts:43:5 - (ae-forgotten-export) The symbol "EntityLayoutProps" needs to be exported by the entry point index.d.ts -// src/components/EntityLayout/EntityLayout.d.ts:44:5 - (ae-forgotten-export) The symbol "SubRoute" needs to be exported by the entry point index.d.ts -// src/components/EntityPageLayout/EntityPageLayout.d.ts:22:5 - (ae-forgotten-export) The symbol "EntityPageLayoutProps" needs to be exported by the entry point index.d.ts -// src/plugin.d.ts:22:5 - (ae-forgotten-export) The symbol "ColumnBreakpoints" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index a2492aaba7..e0cad23f3e 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "0.7.12", + "version": "0.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,25 +24,26 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/search-common": "^0.2.3", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -54,11 +58,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog/src/CatalogClientWrapper.test.ts b/plugins/catalog/src/CatalogClientWrapper.test.ts deleted file mode 100644 index e1bba9e60f..0000000000 --- a/plugins/catalog/src/CatalogClientWrapper.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { CatalogClient } from '@backstage/catalog-client'; -import { CatalogClientWrapper } from './CatalogClientWrapper'; -import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; - -jest.mock('@backstage/catalog-client'); -const MockedCatalogClient = CatalogClient as jest.Mock; - -const mockBaseUrl = 'http://backstage:9191/i-am-a-mock-base'; -const discoveryApi: DiscoveryApi = { - async getBaseUrl(_pluginId) { - return mockBaseUrl; - }, -}; -const identityApi: IdentityApi = { - signOut: jest.fn(), - getProfileInfo: jest.fn(), - getBackstageIdentity: jest.fn(), - getCredentials: jest.fn().mockResolvedValue({ token: 'fake-id-token' }), -}; -const guestIdentityApi: IdentityApi = { - signOut: jest.fn(), - getProfileInfo: jest.fn(), - getBackstageIdentity: jest.fn(), - getCredentials: jest.fn().mockResolvedValue({ token: undefined }), -}; - -describe('CatalogClientWrapper', () => { - beforeEach(() => { - MockedCatalogClient.mockClear(); - }); - - describe('getEntities', () => { - it('injects authorization token', async () => { - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi, - }); - await client.getEntities(); - const getEntities = MockedCatalogClient.mock.instances[0].getEntities; - expect(getEntities).toHaveBeenCalledWith(undefined, { - token: 'fake-id-token', - }); - expect(getEntities).toHaveBeenCalledTimes(1); - }); - }); - - describe('getLocationById', () => { - it('omits authorization token when guest', async () => { - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi: guestIdentityApi, - }); - await client.getLocationById('42'); - const getLocationById = - MockedCatalogClient.mock.instances[0].getLocationById; - expect(getLocationById).toHaveBeenCalledWith('42', {}); - expect(getLocationById).toHaveBeenCalledTimes(1); - }); - }); - - describe('getEntityByName', () => { - const name = { - kind: 'kind', - namespace: 'namespace', - name: 'name', - }; - it('injects authorization token', async () => { - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi, - }); - await client.getEntityByName(name); - const getEntityByName = - MockedCatalogClient.mock.instances[0].getEntityByName; - expect(getEntityByName).toHaveBeenCalledWith(name, { - token: 'fake-id-token', - }); - expect(getEntityByName).toHaveBeenCalledTimes(1); - }); - }); - - describe('addLocation', () => { - const location = { target: 'target' }; - it('injects authorization token', async () => { - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi, - }); - await client.addLocation(location); - const addLocation = MockedCatalogClient.mock.instances[0].addLocation; - expect(addLocation).toHaveBeenCalledWith(location, { - token: 'fake-id-token', - }); - expect(addLocation).toHaveBeenCalledTimes(1); - }); - }); - - describe('getLocationByEntity', () => { - const entity = { - apiVersion: 'apiVersion', - kind: 'kind', - metadata: { - name: 'name', - }, - }; - it('injects authorization token', async () => { - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi, - }); - await client.getLocationByEntity(entity); - const getLocationByEntity = - MockedCatalogClient.mock.instances[0].getLocationByEntity; - expect(getLocationByEntity).toHaveBeenCalledWith(entity, { - token: 'fake-id-token', - }); - expect(getLocationByEntity).toHaveBeenCalledTimes(1); - }); - }); - - describe('removeEntityByUid', () => { - it('injects authorization token', async () => { - const uid = 'uid'; - const client = new CatalogClientWrapper({ - client: new MockedCatalogClient({ discoveryApi }), - identityApi, - }); - await client.removeEntityByUid(uid); - const removeEntityByUid = - MockedCatalogClient.mock.instances[0].removeEntityByUid; - expect(removeEntityByUid).toHaveBeenCalledWith(uid, { - token: 'fake-id-token', - }); - expect(removeEntityByUid).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/plugins/catalog/src/CatalogClientWrapper.ts b/plugins/catalog/src/CatalogClientWrapper.ts deleted file mode 100644 index 939c4f095b..0000000000 --- a/plugins/catalog/src/CatalogClientWrapper.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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, EntityName, Location } from '@backstage/catalog-model'; -import { - AddLocationRequest, - AddLocationResponse, - CatalogApi, - CatalogClient, - CatalogEntitiesRequest, - CatalogListResponse, - CatalogRequestOptions, - CatalogEntityAncestorsRequest, - CatalogEntityAncestorsResponse, -} from '@backstage/catalog-client'; -import { IdentityApi } from '@backstage/core-plugin-api'; - -/** - * CatalogClient wrapper that injects identity token for all requests - * - * @deprecated The default catalog client now uses the `fetchApiRef` - * implementation, which in turn by default issues tokens just the same as this - * class used to assist in doing. If you use a custom `fetchApiRef` - * implementation that does NOT issue tokens, or use a custom `catalogApiRef` - * implementation which does not use the default `fetchApiRef`, you can wrap - * your catalog API in this class to get back the old behavior. - */ -export class CatalogClientWrapper implements CatalogApi { - private readonly identityApi: IdentityApi; - private readonly client: CatalogClient; - - constructor(options: { client: CatalogClient; identityApi: IdentityApi }) { - this.client = options.client; - this.identityApi = options.identityApi; - } - - async getLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.getLocationById( - id, - await this.getCredentials(options), - ); - } - - async getEntities( - request?: CatalogEntitiesRequest, - options?: CatalogRequestOptions, - ): Promise> { - return await this.client.getEntities( - request, - await this.getCredentials(options), - ); - } - - async getEntityByName( - compoundName: EntityName, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.getEntityByName( - compoundName, - await this.getCredentials(options), - ); - } - - async addLocation( - request: AddLocationRequest, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.addLocation( - request, - await this.getCredentials(options), - ); - } - - async getOriginLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.getOriginLocationByEntity( - entity, - await this.getCredentials(options), - ); - } - - async getLocationByEntity( - entity: Entity, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.getLocationByEntity( - entity, - await this.getCredentials(options), - ); - } - - async removeLocationById( - id: string, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.removeLocationById( - id, - await this.getCredentials(options), - ); - } - - async removeEntityByUid( - uid: string, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.removeEntityByUid( - uid, - await this.getCredentials(options), - ); - } - - async refreshEntity( - entityRef: string, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.refreshEntity( - entityRef, - await this.getCredentials(options), - ); - } - - async getEntityAncestors( - request: CatalogEntityAncestorsRequest, - options?: CatalogRequestOptions, - ): Promise { - return await this.client.getEntityAncestors( - request, - await this.getCredentials(options), - ); - } - - private async getCredentials( - options?: CatalogRequestOptions, - ): Promise<{ token?: string }> { - if (options?.token) { - return { token: options?.token }; - } - return this.identityApi.getCredentials(); - } -} diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx index 4ef97b3d46..74c6490534 100644 --- a/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutCard.test.tsx @@ -38,7 +38,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), } as any; diff --git a/plugins/catalog/src/components/AboutCard/AboutCard.tsx b/plugins/catalog/src/components/AboutCard/AboutCard.tsx index a6c9635db2..25383c8ad3 100644 --- a/plugins/catalog/src/components/AboutCard/AboutCard.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutCard.tsx @@ -15,9 +15,8 @@ */ import { - Entity, - ENTITY_DEFAULT_NAMESPACE, - LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model'; import { @@ -72,13 +71,21 @@ const useStyles = makeStyles({ }, }); -type AboutCardProps = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; +/** + * Props for {@link AboutCard}. + * + * @public + */ +export interface AboutCardProps { variant?: InfoCardVariants; -}; +} -export function AboutCard({ variant }: AboutCardProps) { +/** + * @public + * @deprecated Please use EntityAboutCard instead + */ +export function AboutCard(props: AboutCardProps) { + const { variant } = props; const classes = useStyles(); const { entity } = useEntity(); const scmIntegrationsApi = useApi(scmIntegrationsApiRef); @@ -107,7 +114,7 @@ export function AboutCard({ variant }: AboutCardProps) { href: viewTechdocLink && viewTechdocLink({ - namespace: entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE, + namespace: entity.metadata.namespace || DEFAULT_NAMESPACE, kind: entity.kind, name: entity.metadata.name, }), @@ -127,7 +134,7 @@ export function AboutCard({ variant }: AboutCardProps) { cardContentClass = classes.fullHeightCardContent; } - const entityLocation = entity.metadata.annotations?.[LOCATION_ANNOTATION]; + const entityLocation = entity.metadata.annotations?.[ANNOTATION_LOCATION]; // Limiting the ability to manually refresh to the less expensive locations const allowRefresh = entityLocation?.startsWith('url:') || entityLocation?.startsWith('file:'); diff --git a/plugins/catalog/src/components/AboutCard/AboutContent.tsx b/plugins/catalog/src/components/AboutCard/AboutContent.tsx index 9c8260c14d..ee1dad5d39 100644 --- a/plugins/catalog/src/components/AboutCard/AboutContent.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutContent.tsx @@ -33,11 +33,18 @@ const useStyles = makeStyles({ }, }); -type Props = { +/** + * Props for {@link AboutContent}. + * + * @public + */ +export interface AboutContentProps { entity: Entity; -}; +} -export const AboutContent = ({ entity }: Props) => { +/** @public */ +export function AboutContent(props: AboutContentProps) { + const { entity } = props; const classes = useStyles(); const isSystem = entity.kind.toLocaleLowerCase('en-US') === 'system'; const isResource = entity.kind.toLocaleLowerCase('en-US') === 'resource'; @@ -154,4 +161,4 @@ export const AboutContent = ({ entity }: Props) => { ); -}; +} diff --git a/plugins/catalog/src/components/AboutCard/AboutField.tsx b/plugins/catalog/src/components/AboutCard/AboutField.tsx index c4dd107434..6ceaa4fd7a 100644 --- a/plugins/catalog/src/components/AboutCard/AboutField.tsx +++ b/plugins/catalog/src/components/AboutCard/AboutField.tsx @@ -36,14 +36,21 @@ const useStyles = makeStyles(theme => ({ }, })); -type Props = { +/** + * Props for {@link AboutField}. + * + * @public + */ +export interface AboutFieldProps { label: string; value?: string; gridSizes?: Record; children?: React.ReactNode; -}; +} -export const AboutField = ({ label, value, gridSizes, children }: Props) => { +/** @public */ +export function AboutField(props: AboutFieldProps) { + const { label, value, gridSizes, children } = props; const classes = useStyles(); const childElements = useElementFilter(children, c => c.getElements()); @@ -65,4 +72,4 @@ export const AboutField = ({ label, value, gridSizes, children }: Props) => { {content} ); -}; +} diff --git a/plugins/catalog/src/components/AboutCard/index.ts b/plugins/catalog/src/components/AboutCard/index.ts index 84f6a02380..9660a5e2e2 100644 --- a/plugins/catalog/src/components/AboutCard/index.ts +++ b/plugins/catalog/src/components/AboutCard/index.ts @@ -15,5 +15,8 @@ */ export { AboutCard } from './AboutCard'; +export type { AboutCardProps } from './AboutCard'; export { AboutContent } from './AboutContent'; +export type { AboutContentProps } from './AboutContent'; export { AboutField } from './AboutField'; +export type { AboutFieldProps } from './AboutField'; diff --git a/plugins/catalog/src/components/CatalogEntityPage/CatalogEntityPage.tsx b/plugins/catalog/src/components/CatalogEntityPage/CatalogEntityPage.tsx index 94b9f5eee4..da578a8892 100644 --- a/plugins/catalog/src/components/CatalogEntityPage/CatalogEntityPage.tsx +++ b/plugins/catalog/src/components/CatalogEntityPage/CatalogEntityPage.tsx @@ -21,8 +21,11 @@ import { AsyncEntityProvider, } from '@backstage/plugin-catalog-react'; -export const CatalogEntityPage = () => ( - - - -); +/** @public */ +export function CatalogEntityPage() { + return ( + + + + ); +} diff --git a/plugins/catalog/src/components/CatalogEntityPage/index.ts b/plugins/catalog/src/components/CatalogEntityPage/index.ts index bac02a1529..f57648ae00 100644 --- a/plugins/catalog/src/components/CatalogEntityPage/index.ts +++ b/plugins/catalog/src/components/CatalogEntityPage/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { CatalogEntityPage } from './CatalogEntityPage'; diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx index b320d6d220..795d57df47 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx @@ -16,6 +16,7 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; +import { GetEntityFacetsResponse } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { catalogApiRef, @@ -60,7 +61,15 @@ const entities: Entity[] = [ const apis = TestApiRegistry.from([ catalogApiRef, { - getEntities: jest.fn().mockResolvedValue({ items: entities }), + getEntityFacets: jest.fn().mockResolvedValue({ + facets: { + kind: [ + { value: 'Component', count: 2 }, + { value: 'Template', count: 1 }, + { value: 'System', count: 1 }, + ], + }, + } as GetEntityFacetsResponse), }, ]); diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx index 41c5888d79..6689f3371d 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx @@ -38,13 +38,18 @@ const useStyles = makeStyles((theme: Theme) => }), ); -type CatalogKindHeaderProps = { +/** + * Props for {@link CatalogKindHeader}. + * + * @public + */ +export interface CatalogKindHeaderProps { initialFilter?: string; -}; +} -export const CatalogKindHeader = ({ - initialFilter = 'component', -}: CatalogKindHeaderProps) => { +/** @public */ +export function CatalogKindHeader(props: CatalogKindHeaderProps) { + const { initialFilter = 'component' } = props; const classes = useStyles(); const { kinds: allKinds = [] } = useEntityKinds(); const { updateFilters, queryParameters } = useEntityListProvider(); @@ -88,4 +93,4 @@ export const CatalogKindHeader = ({ ))} ); -}; +} diff --git a/plugins/catalog/src/components/CatalogKindHeader/index.ts b/plugins/catalog/src/components/CatalogKindHeader/index.ts index 0078207d58..5a5b20f1a0 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/index.ts +++ b/plugins/catalog/src/components/CatalogKindHeader/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { CatalogKindHeader } from './CatalogKindHeader'; +export type { CatalogKindHeaderProps } from './CatalogKindHeader'; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index cf49cff244..155bcc05df 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -21,8 +21,8 @@ import { DefaultCatalogPageProps, } from './DefaultCatalogPage'; -export const CatalogPage = (props: DefaultCatalogPageProps) => { +export function CatalogPage(props: DefaultCatalogPageProps) { const outlet = useOutlet(); return outlet || ; -}; +} diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index 20acff3c50..34aee0bbf3 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -44,7 +44,7 @@ import DashboardIcon from '@material-ui/icons/Dashboard'; import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { createComponentRouteRef } from '../../routes'; -import { EntityRow } from '../CatalogTable'; +import { CatalogTableRow } from '../CatalogTable'; import { DefaultCatalogPage } from './DefaultCatalogPage'; describe('DefaultCatalogPage', () => { @@ -100,8 +100,8 @@ describe('DefaultCatalogPage', () => { }, ] as Entity[], }), - getLocationByEntity: () => - Promise.resolve({ id: 'id', type: 'github', target: 'url' }), + getLocationByRef: () => + Promise.resolve({ id: 'id', type: 'url', target: 'url' }), getEntityByName: async entityName => { return { apiVersion: 'backstage.io/v1alpha1', @@ -180,7 +180,7 @@ describe('DefaultCatalogPage', () => { }, 20_000); it('should render the custom column passed as prop', async () => { - const columns: TableColumn[] = [ + const columns: TableColumn[] = [ { title: 'Foo', field: 'entity.foo' }, { title: 'Bar', field: 'entity.bar' }, { title: 'Baz', field: 'entity.spec.lifecycle' }, @@ -208,7 +208,7 @@ describe('DefaultCatalogPage', () => { }, 20_000); it('should render the custom actions of an item passed as prop', async () => { - const actions: TableProps['actions'] = [ + const actions: TableProps['actions'] = [ () => { return { icon: () => , diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index 1453a39bbc..8bb9bae764 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -35,8 +35,7 @@ import { } from '@backstage/plugin-catalog-react'; import React from 'react'; import { createComponentRouteRef } from '../../routes'; -import { CatalogTable } from '../CatalogTable'; -import { EntityRow } from '../CatalogTable/types'; +import { CatalogTable, CatalogTableRow } from '../CatalogTable'; import { FilteredEntityLayout, EntityListContainer, @@ -45,20 +44,18 @@ import { import { CatalogKindHeader } from '../CatalogKindHeader'; /** - * DefaultCatalogPageProps + * Props for root catalog pages. + * * @public */ -export type DefaultCatalogPageProps = { +export interface DefaultCatalogPageProps { initiallySelectedFilter?: UserListFilterKind; - columns?: TableColumn[]; - actions?: TableProps['actions']; -}; + columns?: TableColumn[]; + actions?: TableProps['actions']; +} -export const DefaultCatalogPage = ({ - columns, - actions, - initiallySelectedFilter = 'owned', -}: DefaultCatalogPageProps) => { +export function DefaultCatalogPage(props: DefaultCatalogPageProps) { + const { columns, actions, initiallySelectedFilter = 'owned' } = props; const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; const createComponentLink = useRouteRef(createComponentRouteRef); @@ -90,4 +87,4 @@ export const DefaultCatalogPage = ({ ); -}; +} diff --git a/plugins/catalog/src/components/CatalogPage/index.ts b/plugins/catalog/src/components/CatalogPage/index.ts index ca6a13c034..9a3d083f41 100644 --- a/plugins/catalog/src/components/CatalogPage/index.ts +++ b/plugins/catalog/src/components/CatalogPage/index.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { CatalogPage } from './CatalogPage'; export { DefaultCatalogPage } from './DefaultCatalogPage'; export type { DefaultCatalogPageProps } from './DefaultCatalogPage'; diff --git a/plugins/catalog/src/components/CatalogResultListItem/CatalogResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx similarity index 70% rename from plugins/catalog/src/components/CatalogResultListItem/CatalogResultListItem.tsx rename to plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index f0a32ec0e2..54cfe43364 100644 --- a/plugins/catalog/src/components/CatalogResultListItem/CatalogResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -24,6 +24,7 @@ import { makeStyles, } from '@material-ui/core'; import { Link } from '@backstage/core-components'; +import { IndexableDocument } from '@backstage/search-common'; const useStyles = makeStyles({ flexContainer: { @@ -36,7 +37,21 @@ const useStyles = makeStyles({ }, }); -export const CatalogResultListItem = ({ result }: any) => { +/** + * Props for {@link CatalogSearchResultListItem}. + * + * @public + */ +export interface CatalogSearchResultListItemProps { + result: IndexableDocument; +} + +/** @public */ +export function CatalogSearchResultListItem( + props: CatalogSearchResultListItemProps, +) { + const result = props.result as any; + const classes = useStyles(); return ( @@ -57,4 +72,16 @@ export const CatalogResultListItem = ({ result }: any) => { ); -}; +} + +/** + * @public + * @deprecated use {@link CatalogSearchResultListItemProps} instead + */ +export type CatalogResultListItemProps = CatalogSearchResultListItemProps; + +/** + * @public + * @deprecated use {@link CatalogSearchResultListItem} instead + */ +export const CatalogResultListItem = CatalogSearchResultListItem; diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/index.ts b/plugins/catalog/src/components/CatalogSearchResultListItem/index.ts new file mode 100644 index 0000000000..0396117825 --- /dev/null +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { + CatalogSearchResultListItem, + CatalogResultListItem, +} from './CatalogSearchResultListItem'; +export type { + CatalogSearchResultListItemProps, + CatalogResultListItemProps, +} from './CatalogSearchResultListItem'; diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx index 4c6adcf400..db9835e3a3 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx @@ -15,9 +15,9 @@ */ import { - EDIT_URL_ANNOTATION, + ANNOTATION_EDIT_URL, + ANNOTATION_VIEW_URL, Entity, - VIEW_URL_ANNOTATION, } from '@backstage/catalog-model'; import { ApiProvider } from '@backstage/core-app-api'; import { @@ -123,7 +123,7 @@ describe('CatalogTable component', () => { kind: 'Component', metadata: { name: 'component1', - annotations: { [EDIT_URL_ANNOTATION]: 'https://other.place' }, + annotations: { [ANNOTATION_EDIT_URL]: 'https://other.place' }, }, }; @@ -155,7 +155,7 @@ describe('CatalogTable component', () => { kind: 'Component', metadata: { name: 'component1', - annotations: { [VIEW_URL_ANNOTATION]: 'https://other.place' }, + annotations: { [ANNOTATION_VIEW_URL]: 'https://other.place' }, }, }; diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index f293710847..ec4868c20a 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -28,8 +28,8 @@ import Edit from '@material-ui/icons/Edit'; import OpenInNew from '@material-ui/icons/OpenInNew'; import { capitalize } from 'lodash'; import React, { useMemo } from 'react'; -import * as columnFactories from './columns'; -import { EntityRow } from './types'; +import { columnFactories } from './columns'; +import { CatalogTableRow } from './types'; import { CodeSnippet, Table, @@ -38,16 +38,23 @@ import { WarningPanel, } from '@backstage/core-components'; -type CatalogTableProps = { - columns?: TableColumn[]; - actions?: TableProps['actions']; -}; +/** + * Props for {@link CatalogTable}. + * + * @public + */ +export interface CatalogTableProps { + columns?: TableColumn[]; + actions?: TableProps['actions']; +} -export const CatalogTable = ({ columns, actions }: CatalogTableProps) => { +/** @public */ +export const CatalogTable = (props: CatalogTableProps) => { + const { columns, actions } = props; const { isStarredEntity, toggleStarredEntity } = useStarredEntities(); const { loading, error, entities, filters } = useEntityListProvider(); - const defaultColumns: TableColumn[] = useMemo( + const defaultColumns: TableColumn[] = useMemo( () => [ columnFactories.createNameColumn({ defaultKind: filters.kind?.value }), columnFactories.createSystemColumn(), @@ -77,7 +84,7 @@ export const CatalogTable = ({ columns, actions }: CatalogTableProps) => { ); } - const defaultActions: TableProps['actions'] = [ + const defaultActions: TableProps['actions'] = [ ({ entity }) => { const url = getEntityMetadataViewUrl(entity); return { @@ -148,7 +155,7 @@ export const CatalogTable = ({ columns, actions }: CatalogTableProps) => { const showPagination = rows.length > 20; return ( - + isLoading={loading} columns={columns || defaultColumns} options={{ diff --git a/plugins/catalog/src/components/CatalogTable/columns.tsx b/plugins/catalog/src/components/CatalogTable/columns.tsx index 683ac33132..d243be7c6f 100644 --- a/plugins/catalog/src/components/CatalogTable/columns.tsx +++ b/plugins/catalog/src/components/CatalogTable/columns.tsx @@ -20,120 +20,115 @@ import { EntityRefLinks, } from '@backstage/plugin-catalog-react'; import { Chip } from '@material-ui/core'; -import { EntityRow } from './types'; +import { CatalogTableRow } from './types'; import { OverflowTooltip, TableColumn } from '@backstage/core-components'; import { Entity } from '@backstage/catalog-model'; -type NameColumnProps = { - defaultKind?: string; -}; +// The columnFactories symbol is not directly exported, but through the +// CatalogTable.columns field. +/** @public */ +export const columnFactories = Object.freeze({ + createNameColumn(options?: { + defaultKind?: string; + }): TableColumn { + function formatContent(entity: Entity): string { + return ( + entity.metadata?.title || + formatEntityRefTitle(entity, { + defaultKind: options?.defaultKind, + }) + ); + } -export function createNameColumn( - props?: NameColumnProps, -): TableColumn { - function formatContent(entity: Entity): string { - return ( - entity.metadata?.title || - formatEntityRefTitle(entity, { - defaultKind: props?.defaultKind, - }) - ); - } - - return { - title: 'Name', - field: 'resolved.name', - highlight: true, - customSort({ entity: entity1 }, { entity: entity2 }) { - // TODO: We could implement this more efficiently by comparing field by field. - // This has similar issues as above. - return formatContent(entity1).localeCompare(formatContent(entity2)); - }, - render: ({ entity }) => ( - - ), - }; -} - -export function createSystemColumn(): TableColumn { - return { - title: 'System', - field: 'resolved.partOfSystemRelationTitle', - render: ({ resolved }) => ( - - ), - }; -} - -export function createOwnerColumn(): TableColumn { - return { - title: 'Owner', - field: 'resolved.ownedByRelationsTitle', - render: ({ resolved }) => ( - - ), - }; -} - -export function createSpecTypeColumn(): TableColumn { - return { - title: 'Type', - field: 'entity.spec.type', - hidden: true, - }; -} - -export function createSpecLifecycleColumn(): TableColumn { - return { - title: 'Lifecycle', - field: 'entity.spec.lifecycle', - }; -} - -export function createMetadataDescriptionColumn(): TableColumn { - return { - title: 'Description', - field: 'entity.metadata.description', - render: ({ entity }) => ( - - ), - width: 'auto', - }; -} - -export function createTagsColumn(): TableColumn { - return { - title: 'Tags', - field: 'entity.metadata.tags', - cellStyle: { - padding: '0px 16px 0px 20px', - }, - render: ({ entity }) => ( - <> - {entity.metadata.tags && - entity.metadata.tags.map(t => ( - - ))} - - ), - }; -} + return { + title: 'Name', + field: 'resolved.name', + highlight: true, + customSort({ entity: entity1 }, { entity: entity2 }) { + // TODO: We could implement this more efficiently by comparing field by field. + // This has similar issues as above. + return formatContent(entity1).localeCompare(formatContent(entity2)); + }, + render: ({ entity }) => ( + + ), + }; + }, + createSystemColumn(): TableColumn { + return { + title: 'System', + field: 'resolved.partOfSystemRelationTitle', + render: ({ resolved }) => ( + + ), + }; + }, + createOwnerColumn(): TableColumn { + return { + title: 'Owner', + field: 'resolved.ownedByRelationsTitle', + render: ({ resolved }) => ( + + ), + }; + }, + createSpecTypeColumn(): TableColumn { + return { + title: 'Type', + field: 'entity.spec.type', + hidden: true, + }; + }, + createSpecLifecycleColumn(): TableColumn { + return { + title: 'Lifecycle', + field: 'entity.spec.lifecycle', + }; + }, + createMetadataDescriptionColumn(): TableColumn { + return { + title: 'Description', + field: 'entity.metadata.description', + render: ({ entity }) => ( + + ), + width: 'auto', + }; + }, + createTagsColumn(): TableColumn { + return { + title: 'Tags', + field: 'entity.metadata.tags', + cellStyle: { + padding: '0px 16px 0px 20px', + }, + render: ({ entity }) => ( + <> + {entity.metadata.tags && + entity.metadata.tags.map(t => ( + + ))} + + ), + }; + }, +}); diff --git a/plugins/catalog/src/components/CatalogTable/index.ts b/plugins/catalog/src/components/CatalogTable/index.ts index e1660d6c5a..4e1b90f80a 100644 --- a/plugins/catalog/src/components/CatalogTable/index.ts +++ b/plugins/catalog/src/components/CatalogTable/index.ts @@ -15,4 +15,5 @@ */ export { CatalogTable } from './CatalogTable'; -export type { EntityRow } from './types'; +export type { CatalogTableProps } from './CatalogTable'; +export type { CatalogTableRow } from './types'; diff --git a/plugins/catalog/src/components/CatalogTable/types.ts b/plugins/catalog/src/components/CatalogTable/types.ts index 85926becc3..7eaff6faed 100644 --- a/plugins/catalog/src/components/CatalogTable/types.ts +++ b/plugins/catalog/src/components/CatalogTable/types.ts @@ -13,9 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Entity, EntityName } from '@backstage/catalog-model'; -export type EntityRow = { +/** @public */ +export interface CatalogTableRow { entity: Entity; resolved: { name: string; @@ -24,4 +26,4 @@ export type EntityRow = { ownedByRelationsTitle?: string; ownedByRelations: EntityName[]; }; -}; +} diff --git a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.tsx b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.tsx index 34057d7bed..b85a446b75 100644 --- a/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.tsx +++ b/plugins/catalog/src/components/DependencyOfComponentsCard/DependencyOfComponentsCard.tsx @@ -23,15 +23,16 @@ import { RelatedEntitiesCard, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface DependencyOfComponentsCardProps { variant?: 'gridItem'; title?: string; -}; +} -export const DependencyOfComponentsCard = ({ - variant = 'gridItem', - title = 'Dependency of components', -}: Props) => { +export function DependencyOfComponentsCard( + props: DependencyOfComponentsCardProps, +) { + const { variant = 'gridItem', title = 'Dependency of components' } = props; return ( ); -}; +} diff --git a/plugins/catalog/src/components/DependencyOfComponentsCard/index.ts b/plugins/catalog/src/components/DependencyOfComponentsCard/index.ts index bf953fe986..3d324e865d 100644 --- a/plugins/catalog/src/components/DependencyOfComponentsCard/index.ts +++ b/plugins/catalog/src/components/DependencyOfComponentsCard/index.ts @@ -15,3 +15,4 @@ */ export { DependencyOfComponentsCard } from './DependencyOfComponentsCard'; +export type { DependencyOfComponentsCardProps } from './DependencyOfComponentsCard'; diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx index 7e176139ad..33e8caf870 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx +++ b/plugins/catalog/src/components/DependsOnComponentsCard/DependsOnComponentsCard.tsx @@ -23,15 +23,14 @@ import { RelatedEntitiesCard, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface DependsOnComponentsCardProps { variant?: 'gridItem'; title?: string; -}; +} -export const DependsOnComponentsCard = ({ - variant = 'gridItem', - title = 'Depends on components', -}: Props) => { +export function DependsOnComponentsCard(props: DependsOnComponentsCardProps) { + const { variant = 'gridItem', title = 'Depends on components' } = props; return ( ); -}; +} diff --git a/plugins/catalog/src/components/DependsOnComponentsCard/index.ts b/plugins/catalog/src/components/DependsOnComponentsCard/index.ts index 96525fe241..8292526270 100644 --- a/plugins/catalog/src/components/DependsOnComponentsCard/index.ts +++ b/plugins/catalog/src/components/DependsOnComponentsCard/index.ts @@ -15,3 +15,4 @@ */ export { DependsOnComponentsCard } from './DependsOnComponentsCard'; +export type { DependsOnComponentsCardProps } from './DependsOnComponentsCard'; diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx index 34a8e5824d..3fe29093fe 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx +++ b/plugins/catalog/src/components/DependsOnResourcesCard/DependsOnResourcesCard.tsx @@ -23,11 +23,13 @@ import { resourceEntityColumns, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface DependsOnResourcesCardProps { variant?: 'gridItem'; -}; +} -export const DependsOnResourcesCard = ({ variant = 'gridItem' }: Props) => { +export function DependsOnResourcesCard(props: DependsOnResourcesCardProps) { + const { variant = 'gridItem' } = props; return ( { asRenderableEntities={asResourceEntities} /> ); -}; +} diff --git a/plugins/catalog/src/components/DependsOnResourcesCard/index.ts b/plugins/catalog/src/components/DependsOnResourcesCard/index.ts index 5ff94d3542..8d638e16a2 100644 --- a/plugins/catalog/src/components/DependsOnResourcesCard/index.ts +++ b/plugins/catalog/src/components/DependsOnResourcesCard/index.ts @@ -15,3 +15,4 @@ */ export { DependsOnResourcesCard } from './DependsOnResourcesCard'; +export type { DependsOnResourcesCardProps } from './DependsOnResourcesCard'; diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 7bda1f4629..ee677c5238 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -41,30 +41,31 @@ const useStyles = makeStyles({ // NOTE(freben): Intentionally not exported at this point, since it's part of // the unstable extra context menu items concept below -type ExtraContextMenuItem = { +interface ExtraContextMenuItem { title: string; Icon: IconComponent; onClick: () => void; -}; +} // unstable context menu option, eg: disable the unregister entity menu -type contextMenuOptions = { +interface contextMenuOptions { disableUnregister: boolean; -}; +} -type Props = { +interface EntityContextMenuProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; UNSTABLE_contextMenuOptions?: contextMenuOptions; onUnregisterEntity: () => void; onInspectEntity: () => void; -}; +} -export const EntityContextMenu = ({ - UNSTABLE_extraContextMenuItems, - UNSTABLE_contextMenuOptions, - onUnregisterEntity, - onInspectEntity, -}: Props) => { +export function EntityContextMenu(props: EntityContextMenuProps) { + const { + UNSTABLE_extraContextMenuItems, + UNSTABLE_contextMenuOptions, + onUnregisterEntity, + onInspectEntity, + } = props; const [anchorEl, setAnchorEl] = useState(); const classes = useStyles(); const unregisterPermission = useEntityPermission( @@ -150,4 +151,4 @@ export const EntityContextMenu = ({ ); -}; +} diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 144e5d01a8..42658109f9 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -16,7 +16,7 @@ import { Entity, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, RELATION_OWNED_BY, } from '@backstage/catalog-model'; import { @@ -49,7 +49,8 @@ import React, { useContext, useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router'; import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; -type SubRoute = { +/** @public */ +export type EntityLayoutRouteProps = { path: string; title: string; children: JSX.Element; @@ -59,19 +60,15 @@ type SubRoute = { const dataKey = 'plugin.catalog.entityLayoutRoute'; -const Route: (props: SubRoute) => null = () => null; +const Route: (props: EntityLayoutRouteProps) => null = () => null; attachComponentData(Route, dataKey, true); +attachComponentData(Route, 'core.gatherMountPoints', true); // This causes all mount points that are discovered within this route to use the path of the route itself -// This causes all mount points that are discovered within this route to use the path of the route itself -attachComponentData(Route, 'core.gatherMountPoints', true); - -const EntityLayoutTitle = ({ - entity, - title, -}: { +function EntityLayoutTitle(props: { title: string; entity: Entity | undefined; -}) => { +}) { + const { entity, title } = props; return ( } ); -}; +} -const headerProps = ( +function headerProps( paramKind: string | undefined, paramNamespace: string | undefined, paramName: string | undefined, entity: Entity | undefined, -): { headerTitle: string; headerType: string } => { +): { headerTitle: string; headerType: string } { const kind = paramKind ?? entity?.kind ?? ''; const namespace = paramNamespace ?? entity?.metadata.namespace ?? ''; const name = entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? ''; return { headerTitle: `${name}${ - namespace && namespace !== ENTITY_DEFAULT_NAMESPACE - ? ` in ${namespace}` - : '' + namespace && namespace !== DEFAULT_NAMESPACE ? ` in ${namespace}` : '' }`, headerType: (() => { let t = kind.toLocaleLowerCase('en-US'); @@ -112,9 +107,10 @@ const headerProps = ( return t; })(), }; -}; +} -const EntityLabels = ({ entity }: { entity: Entity }) => { +function EntityLabels(props: { entity: Entity }) { + const { entity } = props; const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY); return ( <> @@ -135,26 +131,27 @@ const EntityLabels = ({ entity }: { entity: Entity }) => { )} ); -}; +} // NOTE(freben): Intentionally not exported at this point, since it's part of // the unstable extra context menu items concept below -type ExtraContextMenuItem = { +interface ExtraContextMenuItem { title: string; Icon: IconComponent; onClick: () => void; -}; +} // unstable context menu option, eg: disable the unregister entity menu -type contextMenuOptions = { +interface contextMenuOptions { disableUnregister: boolean; -}; +} -type EntityLayoutProps = { +/** @public */ +export interface EntityLayoutProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; UNSTABLE_contextMenuOptions?: contextMenuOptions; children?: React.ReactNode; -}; +} /** * EntityLayout is a compound component, which allows you to define a layout for @@ -170,12 +167,15 @@ type EntityLayoutProps = { * * * ``` + * + * @public */ -export const EntityLayout = ({ - UNSTABLE_extraContextMenuItems, - UNSTABLE_contextMenuOptions, - children, -}: EntityLayoutProps) => { +export const EntityLayout = (props: EntityLayoutProps) => { + const { + UNSTABLE_extraContextMenuItems, + UNSTABLE_contextMenuOptions, + children, + } = props; const { kind, namespace, name } = useEntityCompoundName(); const { entity, loading, error } = useContext(EntityContext); const location = useLocation(); @@ -188,18 +188,18 @@ export const EntityLayout = ({ withStrictError: 'Child of EntityLayout must be an EntityLayout.Route', }) - .getElements() // all nodes, element data, maintain structure or not? - .flatMap(({ props }) => { - if (props.if && entity && !props.if(entity)) { + .getElements() // all nodes, element data, maintain structure or not? + .flatMap(({ props: elementProps }) => { + if (elementProps.if && entity && !elementProps.if(entity)) { return []; } return [ { - path: props.path, - title: props.title, - children: props.children, - tabProps: props.tabProps, + path: elementProps.path, + title: elementProps.title, + children: elementProps.children, + tabProps: elementProps.tabProps, }, ]; }), diff --git a/plugins/catalog/src/components/EntityLayout/index.ts b/plugins/catalog/src/components/EntityLayout/index.ts index 3b0962ae36..251d213637 100644 --- a/plugins/catalog/src/components/EntityLayout/index.ts +++ b/plugins/catalog/src/components/EntityLayout/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { EntityLayout } from './EntityLayout'; +export type { EntityLayoutProps, EntityLayoutRouteProps } from './EntityLayout'; diff --git a/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx b/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx index 20229ceb14..4c4a1ac908 100644 --- a/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/EntityLinksCard.tsx @@ -14,25 +14,23 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; import { EntityLinksEmptyState } from './EntityLinksEmptyState'; import { LinksGridList } from './LinksGridList'; import { ColumnBreakpoints } from './types'; - import { IconComponent, useApp } from '@backstage/core-plugin-api'; import { InfoCard } from '@backstage/core-components'; -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; +/** @public */ +export interface EntityLinksCardProps { cols?: ColumnBreakpoints | number; variant?: 'gridItem'; -}; +} -export const EntityLinksCard = ({ cols = undefined, variant }: Props) => { +export function EntityLinksCard(props: EntityLinksCardProps) { + const { cols = undefined, variant } = props; const { entity } = useEntity(); const app = useApp(); @@ -57,4 +55,4 @@ export const EntityLinksCard = ({ cols = undefined, variant }: Props) => { )} ); -}; +} diff --git a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx index 54325ffb5d..7f95a66700 100644 --- a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx @@ -40,7 +40,7 @@ const useStyles = makeStyles( { name: 'PluginCatalogEntityLinksEmptyState' }, ); -export const EntityLinksEmptyState = () => { +export function EntityLinksEmptyState() { const classes = useStyles(); return ( @@ -68,4 +68,4 @@ export const EntityLinksEmptyState = () => { ); -}; +} diff --git a/plugins/catalog/src/components/EntityLinksCard/IconLink.tsx b/plugins/catalog/src/components/EntityLinksCard/IconLink.tsx index 9a0302a64e..9afdd1f1da 100644 --- a/plugins/catalog/src/components/EntityLinksCard/IconLink.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/IconLink.tsx @@ -17,7 +17,6 @@ import { makeStyles, Box, Typography } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; - import { Link } from '@backstage/core-components'; import { IconComponent } from '@backstage/core-plugin-api'; @@ -32,15 +31,12 @@ const useStyles = makeStyles({ }, }); -export const IconLink = ({ - href, - text, - Icon, -}: { +export function IconLink(props: { href: string; text?: string; Icon?: IconComponent; -}) => { +}) { + const { href, text, Icon } = props; const classes = useStyles(); return ( @@ -57,4 +53,4 @@ export const IconLink = ({ ); -}; +} diff --git a/plugins/catalog/src/components/EntityLinksCard/LinksGridList.tsx b/plugins/catalog/src/components/EntityLinksCard/LinksGridList.tsx index 3df38c4523..7861b177ce 100644 --- a/plugins/catalog/src/components/EntityLinksCard/LinksGridList.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/LinksGridList.tsx @@ -21,18 +21,19 @@ import { ColumnBreakpoints } from './types'; import { useDynamicColumns } from './useDynamicColumns'; import { IconComponent } from '@backstage/core-plugin-api'; -export type LinksGridListItem = { +export interface LinksGridListItem { href: string; text?: string; Icon?: IconComponent; -}; +} -type Props = { +interface LinksGridListProps { items: LinksGridListItem[]; cols?: ColumnBreakpoints | number; -}; +} -export const LinksGridList = ({ items, cols = undefined }: Props) => { +export function LinksGridList(props: LinksGridListProps) { + const { items, cols = undefined } = props; const numOfCols = useDynamicColumns(cols); return ( @@ -44,4 +45,4 @@ export const LinksGridList = ({ items, cols = undefined }: Props) => { ))} ); -}; +} diff --git a/plugins/catalog/src/components/EntityLinksCard/index.ts b/plugins/catalog/src/components/EntityLinksCard/index.ts index fc53904a47..dcd4366066 100644 --- a/plugins/catalog/src/components/EntityLinksCard/index.ts +++ b/plugins/catalog/src/components/EntityLinksCard/index.ts @@ -15,4 +15,5 @@ */ export { EntityLinksCard } from './EntityLinksCard'; +export type { EntityLinksCardProps } from './EntityLinksCard'; export type { EntityLinksEmptyStateClassKey } from './EntityLinksEmptyState'; diff --git a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx index faaba13d78..4f16078eb9 100644 --- a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx +++ b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.test.tsx @@ -16,7 +16,6 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; - import { EntityNotFound } from './EntityNotFound'; describe('', () => { diff --git a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx index e396e5b4aa..fca763c37b 100644 --- a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx +++ b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx @@ -18,7 +18,6 @@ import React from 'react'; import { Grid, Button, Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; - import { Illo } from './Illo'; const useStyles = makeStyles(theme => ({ @@ -43,7 +42,7 @@ const useStyles = makeStyles(theme => ({ }, })); -export const EntityNotFound = () => { +export function EntityNotFound() { const classes = useStyles(); return ( @@ -67,4 +66,4 @@ export const EntityNotFound = () => { ); -}; +} diff --git a/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx b/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx index e0e76cd5d4..a375eca02a 100644 --- a/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx +++ b/plugins/catalog/src/components/EntityNotFound/Illo/Illo.tsx @@ -34,7 +34,7 @@ const useStyles = makeStyles(theme => ({ }, })); -export const Illo = () => { +export function Illo() { const classes = useStyles(); return ( { alt="Illustration on entity not found page" /> ); -}; +} diff --git a/plugins/catalog/src/components/EntityNotFound/index.ts b/plugins/catalog/src/components/EntityNotFound/index.ts index 700a1097ca..aa2bd8e82b 100644 --- a/plugins/catalog/src/components/EntityNotFound/index.ts +++ b/plugins/catalog/src/components/EntityNotFound/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { EntityNotFound } from './EntityNotFound'; diff --git a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx index f58e6b9b66..c5442f3a3d 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.test.tsx @@ -13,15 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import userEvent from '@testing-library/user-event'; import React from 'react'; import { DeleteEntityDialog } from './DeleteEntityDialog'; -import { ORIGIN_LOCATION_ANNOTATION } from '@backstage/catalog-model'; +import { ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { CatalogApi } from '@backstage/catalog-client'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { screen, waitFor } from '@testing-library/react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; - import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; describe('DeleteEntityDialog', () => { @@ -42,7 +42,7 @@ describe('DeleteEntityDialog', () => { name: 'n', namespace: 'ns', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:http://example.com', + [ANNOTATION_ORIGIN_LOCATION]: 'url:http://example.com', }, }, spec: {}, diff --git a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx index 20aa673ea3..fc1391152a 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx @@ -21,19 +21,15 @@ import React, { useState } from 'react'; import { alertApiRef, useApi } from '@backstage/core-plugin-api'; import { assertError } from '@backstage/errors'; -type Props = { +interface DeleteEntityDialogProps { open: boolean; onClose: () => any; onConfirm: () => any; entity: Entity; -}; +} -export const DeleteEntityDialog = ({ - open, - onClose, - onConfirm, - entity, -}: Props) => { +export function DeleteEntityDialog(props: DeleteEntityDialogProps) { + const { open, onClose, onConfirm, entity } = props; const [busy, setBusy] = useState(false); const catalogApi = useApi(catalogApiRef); const alertApi = useApi(alertApiRef); @@ -72,4 +68,4 @@ export const DeleteEntityDialog = ({ ); -}; +} diff --git a/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.tsx b/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.tsx index c9d2d94609..aba28c558f 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/EntityOrphanWarning.tsx @@ -22,13 +22,23 @@ import { useNavigate } from 'react-router'; import { DeleteEntityDialog } from './DeleteEntityDialog'; import { useRouteRef } from '@backstage/core-plugin-api'; -export const isOrphan = (entity: Entity) => - entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true'; +/** + * Returns true if the given entity has the orphan annotation given by the + * catalog. + * + * @public + */ +export function isOrphan(entity: Entity): boolean { + return entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true'; +} /** - * Displays a warning alert if the entity is marked as orphan with the ability to delete said entity. + * Displays a warning alert if the entity is marked as orphan with the ability + * to delete said entity. + * + * @public */ -export const EntityOrphanWarning = () => { +export function EntityOrphanWarning() { const navigate = useNavigate(); const catalogLink = useRouteRef(catalogRouteRef); const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false); @@ -53,4 +63,4 @@ export const EntityOrphanWarning = () => { /> ); -}; +} diff --git a/plugins/catalog/src/components/EntityPageLayout/EntityPageLayout.tsx b/plugins/catalog/src/components/EntityPageLayout/EntityPageLayout.tsx deleted file mode 100644 index 82a980afcb..0000000000 --- a/plugins/catalog/src/components/EntityPageLayout/EntityPageLayout.tsx +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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, - ENTITY_DEFAULT_NAMESPACE, - RELATION_OWNED_BY, -} from '@backstage/catalog-model'; -import { - EntityContext, - EntityRefLinks, - FavoriteEntity, - getEntityRelations, - InspectEntityDialog, - UnregisterEntityDialog, - useEntityCompoundName, -} from '@backstage/plugin-catalog-react'; -import { Box } from '@material-ui/core'; -import React, { useContext, useState } from 'react'; -import { useNavigate } from 'react-router'; -import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; -import { Tabbed } from './Tabbed'; - -import { - Content, - Header, - HeaderLabel, - Link, - Page, - Progress, - ResponseErrorPanel, - WarningPanel, -} from '@backstage/core-components'; - -import { IconComponent } from '@backstage/core-plugin-api'; - -const EntityPageTitle = ({ - entity, - title, -}: { - title: string; - entity: Entity | undefined; -}) => ( - - {title} - {entity && } - -); - -const EntityLabels = ({ entity }: { entity: Entity }) => { - const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY); - return ( - <> - {ownedByRelations.length > 0 && ( - - } - /> - )} - {entity.spec?.lifecycle && ( - - )} - - ); -}; - -const headerProps = ( - kind: string, - namespace: string | undefined, - name: string, - entity: Entity | undefined, -): { headerTitle: string; headerType: string } => { - return { - headerTitle: `${name}${ - namespace && namespace !== ENTITY_DEFAULT_NAMESPACE - ? ` in ${namespace}` - : '' - }`, - headerType: (() => { - let t = kind.toLocaleLowerCase('en-US'); - if (entity && entity.spec && 'type' in entity.spec) { - t += ' β€” '; - t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US'); - } - return t; - })(), - }; -}; - -// NOTE(freben): Intentionally not exported at this point, since it's part of -// the unstable extra context menu items concept below -type ExtraContextMenuItem = { - title: string; - Icon: IconComponent; - onClick: () => void; -}; - -// unstable context menu option, eg: disable the unregister entity menu -type contextMenuOptions = { - disableUnregister: boolean; -}; - -type EntityPageLayoutProps = { - UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; - UNSTABLE_contextMenuOptions?: contextMenuOptions; - children?: React.ReactNode; -}; - -/** - * Old entity page, only used by the old router based hierarchies. - * - * @deprecated Please use CatalogEntityPage instead - */ -export const EntityPageLayout = ({ - children, - UNSTABLE_extraContextMenuItems, - UNSTABLE_contextMenuOptions, -}: EntityPageLayoutProps) => { - const { kind, namespace, name } = useEntityCompoundName(); - const { entity, loading, error } = useContext(EntityContext); - const { headerTitle, headerType } = headerProps( - kind, - namespace, - name, - entity!, - ); - - const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false); - const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false); - const navigate = useNavigate(); - const cleanUpAfterRemoval = async () => { - setConfirmationDialogOpen(false); - navigate('/'); - }; - - return ( - -
} - pageTitleOverride={headerTitle} - type={headerType} - > - {/* TODO: Make entity labels configurable for entity kind / type */} - {entity && ( - <> - - setConfirmationDialogOpen(true)} - onInspectEntity={() => setInspectionDialogOpen(true)} - /> - - )} -
- - {loading && ( - - - - )} - - {entity && {children}} - - {error && ( - - - - )} - - {!loading && !error && !entity && ( - - - There is no {kind} with the requested{' '} - - kind, namespace, and name - - . - - - )} - - setConfirmationDialogOpen(false)} - /> - setInspectionDialogOpen(false)} - /> -
- ); -}; - -EntityPageLayout.Content = Tabbed.Content; diff --git a/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.test.tsx b/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.test.tsx deleted file mode 100644 index ad111380f8..0000000000 --- a/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.test.tsx +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { Tabbed } from './Tabbed'; -import { renderInTestApp } from '@backstage/test-utils'; -import { act, fireEvent } from '@testing-library/react'; -import { Routes, Route } from 'react-router'; - -describe('Tabbed layout', () => { - it('renders simplest case', async () => { - const rendered = await renderInTestApp( - - tabbed-test-content} - /> - , - ); - - expect(rendered.getByText('tabbed-test-title')).toBeInTheDocument(); - expect(rendered.getByText('tabbed-test-content')).toBeInTheDocument(); - }); - - it('throws if any other component is a child of Tabbed.Layout', async () => { - await expect( - renderInTestApp( - - tabbed-test-content} - /> -
This will cause app to throw
-
, - ), - ).rejects.toThrow(/This component only accepts/); - }); - - it('navigates when user clicks different tab', async () => { - const rendered = await renderInTestApp( - - - tabbed-test-content} - /> - tabbed-test-content-2} - /> - - } - /> - , - ); - - const secondTab = rendered.queryAllByRole('tab')[1]; - act(() => { - fireEvent.click(secondTab); - }); - - expect(rendered.getByText('tabbed-test-title')).toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content')).not.toBeInTheDocument(); - - expect(rendered.getByText('tabbed-test-title-2')).toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument(); - }); - - describe('correctly delegates nested links', () => { - const renderRoute = (route: string) => - renderInTestApp( - - - tabbed-test-content} - /> - - tabbed-test-content-2 - - tabbed-test-nested-content-2} - /> - - - } - /> - - } - /> - , - { routeEntries: [route] }, - ); - - it('works for nested content', async () => { - const rendered = await renderRoute('/some-other-path/nested'); - - expect( - rendered.queryByText('tabbed-test-content'), - ).not.toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument(); - expect( - rendered.queryByText('tabbed-test-nested-content-2'), - ).toBeInTheDocument(); - }); - - it('works for non-nested content', async () => { - const rendered = await renderRoute('/some-other-path/'); - - expect( - rendered.queryByText('tabbed-test-content'), - ).not.toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument(); - expect( - rendered.queryByText('tabbed-test-nested-content-2'), - ).not.toBeInTheDocument(); - }); - }); - - it('shows only one tab contents at a time', async () => { - const rendered = await renderInTestApp( - - tabbed-test-content} - /> - tabbed-test-content-2} - /> - , - { routeEntries: ['/some-other-path'] }, - ); - - expect(rendered.getByText('tabbed-test-title')).toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content')).not.toBeInTheDocument(); - - expect(rendered.getByText('tabbed-test-title-2')).toBeInTheDocument(); - expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument(); - }); - - it('redirects to the top level when no route is matching the url', async () => { - const rendered = await renderInTestApp( - - tabbed-test-content} - /> - tabbed-test-content-2} - /> - , - { routeEntries: ['/non-existing-path'] }, - ); - - expect(rendered.getByText('tabbed-test-title')).toBeInTheDocument(); - expect(rendered.getByText('tabbed-test-content')).toBeInTheDocument(); - expect(rendered.getByText('tabbed-test-title-2')).toBeInTheDocument(); - - expect( - rendered.queryByText('tabbed-test-content-2'), - ).not.toBeInTheDocument(); - }); -}); diff --git a/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.tsx b/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.tsx deleted file mode 100644 index 59271d2c60..0000000000 --- a/plugins/catalog/src/components/EntityPageLayout/Tabbed/Tabbed.tsx +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { - useParams, - useNavigate, - PartialRouteObject, - matchRoutes, - RouteObject, - useRoutes, - Navigate, - RouteMatch, -} from 'react-router'; -import { Helmet } from 'react-helmet'; -import { Tab, HeaderTabs, Content } from '@backstage/core-components'; - -const getSelectedIndexOrDefault = ( - matchedRoute: RouteMatch, - tabs: Tab[], - defaultIndex = 0, -) => { - if (!matchedRoute) return defaultIndex; - const tabIndex = tabs.findIndex(t => t.id === matchedRoute.route.path); - return ~tabIndex ? tabIndex : defaultIndex; -}; - -/** - * Compound component, which allows you to define layout - * for EntityPage using Tabs as a sub-navigation mechanism - * Consists of 2 parts: Tabbed.Layout and Tabbed.Content. - * Takes care of: tabs, routes, document titles, spacing around content - * - * @example - * ```jsx - * - * This is rendered under /example/anything-here route} - * /> - * - * ``` - */ -export const Tabbed = { - Layout: ({ children }: { children: React.ReactNode }) => { - const routes: PartialRouteObject[] = []; - const tabs: Tab[] = []; - const params = useParams(); - const navigate = useNavigate(); - - React.Children.forEach(children, child => { - if (!React.isValidElement(child)) { - // Skip conditionals resolved to falses/nulls/undefineds etc - return; - } - if (child.type !== Tabbed.Content) { - throw new Error( - 'This component only accepts Content elements as direct children. Check the code of the EntityPage.', - ); - } - const pathAndId = (child as JSX.Element).props.path; - - // Child here must be then always a functional component without any wrappers - tabs.push({ - id: pathAndId, - label: (child as JSX.Element).props.title, - }); - - routes.push({ - path: pathAndId, - element: child.props.element, - }); - }); - - // Add catch-all for incorrect sub-routes - if ((routes?.[0]?.path ?? '') !== '') - routes.push({ - path: '/*', - element: , - }); - - const [matchedRoute] = - matchRoutes(routes as RouteObject[], `/${params['*']}`) ?? []; - const selectedIndex = getSelectedIndexOrDefault(matchedRoute, tabs); - const currentTab = tabs[selectedIndex]; - const title = currentTab?.label; - - const onTabChange = (index: number) => - // Remove trailing /* - // And remove leading / for relative navigation - // Note! route resolves relative to the position in the React tree, - // not relative to current location - navigate(tabs[index].id.replace(/\/\*$/, '').replace(/^\//, '')); - - const currentRouteElement = useRoutes(routes); - - if (!currentTab) return null; - return ( - <> - - - - {currentRouteElement} - - - ); - }, - Content: (_props: { path: string; title: string; element: JSX.Element }) => - null, -}; diff --git a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx index e4df011b38..2eaf505ec0 100644 --- a/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx +++ b/plugins/catalog/src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx @@ -19,7 +19,6 @@ import { AlphaEntity, stringifyEntityRef, EntityStatusItem, - compareEntityToRef, } from '@backstage/catalog-model'; import { catalogApiRef, @@ -42,12 +41,12 @@ const errorFilter = (i: EntityStatusItem) => i.level === 'error' && i.type === ENTITY_STATUS_CATALOG_PROCESSING_TYPE; -type GetOwnAndAncestorsErrorsResponse = { +interface GetOwnAndAncestorsErrorsResponse { items: { errors: SerializedError[]; entity: Entity; }[]; -}; +} async function getOwnAndAncestorsErrors( entityRef: string, @@ -67,10 +66,15 @@ async function getOwnAndAncestorsErrors( return { items }; } -export const hasCatalogProcessingErrors = async ( +/** + * Returns true if the given entity has any processing errors on it. + * + * @public + */ +export async function hasCatalogProcessingErrors( entity: Entity, context: { apis: ApiHolder }, -) => { +) { const catalogApi = context.apis.get(catalogApiRef); if (!catalogApi) { throw new Error(`No implementation available for ${catalogApiRef}`); @@ -81,12 +85,14 @@ export const hasCatalogProcessingErrors = async ( catalogApi, ); return errors.items.length > 0; -}; +} /** * Displays a list of errors from the ancestors of the current entity. + * + * @public */ -export const EntityProcessingErrorsPanel = () => { +export function EntityProcessingErrorsPanel() { const { entity } = useEntity(); const entityRef = stringifyEntityRef(entity); const catalogApi = useApi(catalogApiRef); @@ -110,10 +116,8 @@ export const EntityProcessingErrorsPanel = () => { <> {value.items.map((ancestorError, index) => ( - {!compareEntityToRef( - entity, - stringifyEntityRef(ancestorError.entity), - ) && ( + {stringifyEntityRef(entity) !== + stringifyEntityRef(ancestorError.entity) && ( The error below originates from{' '} @@ -126,4 +130,4 @@ export const EntityProcessingErrorsPanel = () => { ))} ); -}; +} diff --git a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.tsx b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.tsx index 87ee81c5f4..4433517247 100644 --- a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.tsx +++ b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; -import React, { PropsWithChildren, ReactNode } from 'react'; +import React, { ReactNode, ReactElement } from 'react'; import { attachComponentData, useApiHolder, @@ -27,34 +27,46 @@ import useAsync from 'react-use/lib/useAsync'; const ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch'; -const EntitySwitchCase = (_: { +/** @public */ +export interface EntitySwitchCaseProps { if?: ( entity: Entity, context: { apis: ApiHolder }, ) => boolean | Promise; children: ReactNode; -}) => null; +} -attachComponentData(EntitySwitchCase, ENTITY_SWITCH_KEY, true); +const EntitySwitchCaseComponent = (_props: EntitySwitchCaseProps) => null; -type SwitchCase = { +attachComponentData(EntitySwitchCaseComponent, ENTITY_SWITCH_KEY, true); + +interface EntitySwitchCase { if?: ( entity: Entity, context: { apis: ApiHolder }, ) => boolean | Promise; children: JSX.Element; -}; +} type SwitchCaseResult = { if: boolean | Promise; children: JSX.Element; }; -export const EntitySwitch = ({ children }: PropsWithChildren<{}>) => { +/** + * Props for the {@link EntitySwitch} component. + * @public + */ +export interface EntitySwitchProps { + children: ReactNode; +} + +/** @public */ +export const EntitySwitch = (props: EntitySwitchProps) => { const { entity } = useEntity(); const apis = useApiHolder(); const results = useElementFilter( - children, + props.children, collection => collection .selectByComponentData({ @@ -62,9 +74,9 @@ export const EntitySwitch = ({ children }: PropsWithChildren<{}>) => { withStrictError: 'Child of EntitySwitch is not an EntitySwitch.Case', }) .getElements() - .flatMap((element: React.ReactElement) => { + .flatMap((element: ReactElement) => { const { if: condition, children: elementsChildren } = - element.props as SwitchCase; + element.props as EntitySwitchCase; return [ { if: condition?.(entity, { apis }) ?? true, @@ -110,4 +122,4 @@ function AsyncEntitySwitch({ results }: { results: SwitchCaseResult[] }) { return value; } -EntitySwitch.Case = EntitySwitchCase; +EntitySwitch.Case = EntitySwitchCaseComponent; diff --git a/plugins/catalog/src/components/EntitySwitch/conditions.ts b/plugins/catalog/src/components/EntitySwitch/conditions.ts index dd95a256bc..a02170cc6f 100644 --- a/plugins/catalog/src/components/EntitySwitch/conditions.ts +++ b/plugins/catalog/src/components/EntitySwitch/conditions.ts @@ -22,10 +22,18 @@ function strCmp(a: string | undefined, b: string | undefined): boolean { ); } +/** + * For use in EntitySwitch.Case. Matches if the entity is of a given kind. + * @public + */ export function isKind(kind: string) { return (entity: Entity) => strCmp(entity?.kind, kind); } +/** + * For use in EntitySwitch.Case. Matches if the entity is a Component of a given spec.type. + * @public + */ export function isComponentType(type: string) { return (entity: Entity) => { if (!strCmp(entity?.kind, 'component')) { @@ -36,6 +44,10 @@ export function isComponentType(type: string) { }; } +/** + * For use in EntitySwitch.Case. Matches if the entity is in a given namespace. + * @public + */ export function isNamespace(namespace: string) { return (entity: Entity) => strCmp(entity?.metadata?.namespace, namespace); } diff --git a/plugins/catalog/src/components/EntitySwitch/index.ts b/plugins/catalog/src/components/EntitySwitch/index.ts index bf4caf0e66..6cccf4be6e 100644 --- a/plugins/catalog/src/components/EntitySwitch/index.ts +++ b/plugins/catalog/src/components/EntitySwitch/index.ts @@ -15,4 +15,5 @@ */ export { EntitySwitch } from './EntitySwitch'; +export type { EntitySwitchProps, EntitySwitchCaseProps } from './EntitySwitch'; export { isKind, isNamespace, isComponentType } from './conditions'; diff --git a/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx index a39ef76b87..d210d551fb 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx @@ -15,10 +15,13 @@ */ import { Grid } from '@material-ui/core'; -import React, { PropsWithChildren } from 'react'; +import React from 'react'; -export const EntityListContainer = ({ children }: PropsWithChildren<{}>) => ( - - {children} - -); +/** @public */ +export function EntityListContainer(props: { children: React.ReactNode }) { + return ( + + {props.children} + + ); +} diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx index 683dbf8b40..4c0d17599d 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -25,9 +25,10 @@ import { useTheme, } from '@material-ui/core'; import FilterListIcon from '@material-ui/icons/FilterList'; -import React, { useState, PropsWithChildren } from 'react'; +import React, { useState } from 'react'; -export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { +/** @public */ +export function FilterContainer(props: { children: React.ReactNode }) { const isMidSizeScreen = useMediaQuery(theme => theme.breakpoints.down('md'), ); @@ -59,13 +60,13 @@ export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { > Filters - {children} + {props.children} ) : ( - {children} + {props.children} ); -}; +} diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx index 628ad9fee6..8e595fe5cd 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx @@ -15,10 +15,13 @@ */ import { Grid } from '@material-ui/core'; -import React, { PropsWithChildren } from 'react'; +import React from 'react'; -export const FilteredEntityLayout = ({ children }: PropsWithChildren<{}>) => ( - - {children} - -); +/** @public */ +export function FilteredEntityLayout(props: { children: React.ReactNode }) { + return ( + + {props.children} + + ); +} diff --git a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx index cefdb15a6e..5864028694 100644 --- a/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx +++ b/plugins/catalog/src/components/HasComponentsCard/HasComponentsCard.tsx @@ -23,11 +23,13 @@ import { RelatedEntitiesCard, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface HasComponentsCardProps { variant?: 'gridItem'; -}; +} -export const HasComponentsCard = ({ variant = 'gridItem' }: Props) => { +export function HasComponentsCard(props: HasComponentsCardProps) { + const { variant = 'gridItem' } = props; return ( { asRenderableEntities={asComponentEntities} /> ); -}; +} diff --git a/plugins/catalog/src/components/HasComponentsCard/index.ts b/plugins/catalog/src/components/HasComponentsCard/index.ts index 73088bd575..86038b6030 100644 --- a/plugins/catalog/src/components/HasComponentsCard/index.ts +++ b/plugins/catalog/src/components/HasComponentsCard/index.ts @@ -15,3 +15,4 @@ */ export { HasComponentsCard } from './HasComponentsCard'; +export type { HasComponentsCardProps } from './HasComponentsCard'; diff --git a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx index 3a57317a06..19a48aad25 100644 --- a/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx +++ b/plugins/catalog/src/components/HasResourcesCard/HasResourcesCard.tsx @@ -23,11 +23,13 @@ import { resourceEntityHelpLink, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface HasResourcesCardProps { variant?: 'gridItem'; -}; +} -export const HasResourcesCard = ({ variant = 'gridItem' }: Props) => { +export function HasResourcesCard(props: HasResourcesCardProps) { + const { variant = 'gridItem' } = props; return ( { emptyHelpLink={resourceEntityHelpLink} /> ); -}; +} diff --git a/plugins/catalog/src/components/HasResourcesCard/index.ts b/plugins/catalog/src/components/HasResourcesCard/index.ts index 5357643a62..cdbbef680b 100644 --- a/plugins/catalog/src/components/HasResourcesCard/index.ts +++ b/plugins/catalog/src/components/HasResourcesCard/index.ts @@ -15,3 +15,4 @@ */ export { HasResourcesCard } from './HasResourcesCard'; +export type { HasResourcesCardProps } from './HasResourcesCard'; diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx index ddeffe3fbd..0b31bbd2be 100644 --- a/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx +++ b/plugins/catalog/src/components/HasSubcomponentsCard/HasSubcomponentsCard.tsx @@ -22,11 +22,13 @@ import { RelatedEntitiesCard, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface HasSubcomponentsCardProps { variant?: 'gridItem'; -}; +} -export const HasSubcomponentsCard = ({ variant = 'gridItem' }: Props) => { +export function HasSubcomponentsCard(props: HasSubcomponentsCardProps) { + const { variant = 'gridItem' } = props; return ( { emptyHelpLink="https://backstage.io/docs/features/software-catalog/descriptor-format#specsubcomponentof-optional" /> ); -}; +} diff --git a/plugins/catalog/src/components/HasSubcomponentsCard/index.ts b/plugins/catalog/src/components/HasSubcomponentsCard/index.ts index bfc74efe71..6f43967d50 100644 --- a/plugins/catalog/src/components/HasSubcomponentsCard/index.ts +++ b/plugins/catalog/src/components/HasSubcomponentsCard/index.ts @@ -15,3 +15,4 @@ */ export { HasSubcomponentsCard } from './HasSubcomponentsCard'; +export type { HasSubcomponentsCardProps } from './HasSubcomponentsCard'; diff --git a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx index b3e756c8dc..7ab6831e42 100644 --- a/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx +++ b/plugins/catalog/src/components/HasSystemsCard/HasSystemsCard.tsx @@ -23,11 +23,13 @@ import { systemEntityHelpLink, } from '../RelatedEntitiesCard'; -type Props = { +/** @public */ +export interface HasSystemsCardProps { variant?: 'gridItem'; -}; +} -export const HasSystemsCard = ({ variant = 'gridItem' }: Props) => { +export function HasSystemsCard(props: HasSystemsCardProps) { + const { variant = 'gridItem' } = props; return ( { emptyHelpLink={systemEntityHelpLink} /> ); -}; +} diff --git a/plugins/catalog/src/components/HasSystemsCard/index.ts b/plugins/catalog/src/components/HasSystemsCard/index.ts index e69c783bb4..71fb7539b1 100644 --- a/plugins/catalog/src/components/HasSystemsCard/index.ts +++ b/plugins/catalog/src/components/HasSystemsCard/index.ts @@ -15,3 +15,4 @@ */ export { HasSystemsCard } from './HasSystemsCard'; +export type { HasSystemsCardProps } from './HasSystemsCard'; diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx index ec6ea696e2..70854c1b21 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx +++ b/plugins/catalog/src/components/RelatedEntitiesCard/RelatedEntitiesCard.tsx @@ -30,7 +30,8 @@ import { TableColumn, } from '@backstage/core-components'; -type Props = { +/** @public */ +export type RelatedEntitiesCardProps = { variant?: 'gridItem'; title: string; columns: TableColumn[]; @@ -53,7 +54,9 @@ type Props = { * * @public */ -export const RelatedEntitiesCard = (props: Props) => { +export function RelatedEntitiesCard( + props: RelatedEntitiesCardProps, +) { const { variant = 'gridItem', title, @@ -103,4 +106,4 @@ export const RelatedEntitiesCard = (props: Props) => { entities={asRenderableEntities(entities || [])} /> ); -}; +} diff --git a/plugins/catalog/src/components/RelatedEntitiesCard/index.ts b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts index 8df5052de4..6012dd6553 100644 --- a/plugins/catalog/src/components/RelatedEntitiesCard/index.ts +++ b/plugins/catalog/src/components/RelatedEntitiesCard/index.ts @@ -15,4 +15,5 @@ */ export { RelatedEntitiesCard } from './RelatedEntitiesCard'; +export type { RelatedEntitiesCardProps } from './RelatedEntitiesCard'; export * from './presets'; diff --git a/plugins/catalog/src/components/Router.tsx b/plugins/catalog/src/components/Router.tsx deleted file mode 100644 index e8b00d8513..0000000000 --- a/plugins/catalog/src/components/Router.tsx +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; -import { - AsyncEntityProvider, - useEntity, - useEntityFromUrl, -} from '@backstage/plugin-catalog-react'; -import { Typography } from '@material-ui/core'; -import React, { ComponentType, ReactNode } from 'react'; -import { Navigate, Route, Routes, useParams } from 'react-router'; -import { CatalogPage } from './CatalogPage'; -import { EntityNotFound } from './EntityNotFound'; -import { EntityPageLayout } from './EntityPageLayout'; -import { Content, Link } from '@backstage/core-components'; - -const DefaultEntityPage = () => ( - - - This is the default entity page. - - To override this component with your custom implementation, read - docs on{' '} - backstage.io/docs - - - } - /> - -); - -const EntityPageSwitch = ({ EntityPage }: { EntityPage: ComponentType }) => { - const { entity, loading, error } = useEntity(); - // Loading and error states - if (loading) return ; - if (error || !entity) return ; - - // Otherwise EntityPage provided from the App - // Note that EntityPage will include EntityPageLayout already - return ; -}; - -const OldEntityRouteRedirect = () => { - const { optionalNamespaceAndName, '*': rest } = useParams() as any; - const [name, namespace] = optionalNamespaceAndName.split(':').reverse(); - const namespaceLower = - namespace?.toLocaleLowerCase('en-US') ?? ENTITY_DEFAULT_NAMESPACE; - const restWithSlash = rest ? `/${rest}` : ''; - return ( - - ); -}; - -export const EntityLoader = (props: { children: ReactNode }) => ( - -); - -/** - * @deprecated Use plugin extensions instead - * */ -export const Router = ({ - EntityPage = DefaultEntityPage, -}: { - EntityPage?: ComponentType; -}) => ( - - } /> - - - - } - /> - } - /> - -); diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 6c17e4ee67..ec4d13a2f2 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -20,7 +20,7 @@ import { RELATION_PROVIDES_API, RELATION_PART_OF, stringifyEntityRef, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, parseEntityRef, } from '@backstage/catalog-model'; import { @@ -92,7 +92,7 @@ function readableEntityName( ): string { return stringifyEntityRef(ref) .toLocaleLowerCase('en-US') - .replace(`:${ENTITY_DEFAULT_NAMESPACE}/`, ':') + .replace(`:${DEFAULT_NAMESPACE}/`, ':') .split(':')[1]; } @@ -180,7 +180,7 @@ export function SystemDiagramCard() { 'spec.system': [ currentSystemName, `${ - entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE + entity.metadata.namespace || DEFAULT_NAMESPACE }/${currentSystemName}`, ], }, diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 57dd911b2d..0cda2fe6f6 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -20,26 +20,21 @@ * @packageDocumentation */ -export { CatalogClientWrapper } from './CatalogClientWrapper'; export * from './components/AboutCard'; export * from './components/CatalogKindHeader'; -export * from './components/CatalogResultListItem'; -export { CatalogTable } from './components/CatalogTable'; -export type { EntityRow as CatalogTableRow } from './components/CatalogTable'; +export * from './components/CatalogSearchResultListItem'; +export * from './components/CatalogTable'; export * from './components/CatalogTable/columns'; export * from './components/EntityLayout'; export * from './components/EntityOrphanWarning'; export * from './components/EntityProcessingErrorsPanel'; -export * from './components/EntityPageLayout'; export * from './components/EntitySwitch'; export * from './components/FilteredEntityLayout'; export * from './overridableComponents'; -export { Router } from './components/Router'; export { CatalogEntityPage, CatalogIndexPage, catalogPlugin, - catalogPlugin as plugin, EntityAboutCard, EntityDependencyOfComponentsCard, EntityDependsOnComponentsCard, @@ -49,10 +44,20 @@ export { EntityHasSubcomponentsCard, EntityHasSystemsCard, EntityLinksCard, - EntitySystemDiagramCard, RelatedEntitiesCard, } from './plugin'; -export type { EntityLinksEmptyStateClassKey } from './components/EntityLinksCard'; +export type { DependencyOfComponentsCardProps } from './components/DependencyOfComponentsCard'; +export type { DependsOnComponentsCardProps } from './components/DependsOnComponentsCard'; +export type { DependsOnResourcesCardProps } from './components/DependsOnResourcesCard'; +export type { + EntityLinksEmptyStateClassKey, + EntityLinksCardProps, +} from './components/EntityLinksCard'; export type { SystemDiagramCardClassKey } from './components/SystemDiagramCard'; export type { DefaultCatalogPageProps } from './components/CatalogPage'; +export type { HasComponentsCardProps } from './components/HasComponentsCard'; +export type { HasResourcesCardProps } from './components/HasResourcesCard'; +export type { HasSubcomponentsCardProps } from './components/HasSubcomponentsCard'; +export type { HasSystemsCardProps } from './components/HasSystemsCard'; +export type { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard'; diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 5a94cd2a09..b4d1a61bc1 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -15,6 +15,7 @@ */ import { CatalogClient } from '@backstage/catalog-client'; +import { Entity } from '@backstage/catalog-model'; import { catalogApiRef, catalogRouteRef, @@ -32,7 +33,18 @@ import { fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; +import { AboutCardProps } from './components/AboutCard'; +import { DefaultCatalogPageProps } from './components/CatalogPage'; +import { DependencyOfComponentsCardProps } from './components/DependencyOfComponentsCard'; +import { DependsOnComponentsCardProps } from './components/DependsOnComponentsCard'; +import { DependsOnResourcesCardProps } from './components/DependsOnResourcesCard'; +import { HasComponentsCardProps } from './components/HasComponentsCard'; +import { HasResourcesCardProps } from './components/HasResourcesCard'; +import { HasSubcomponentsCardProps } from './components/HasSubcomponentsCard'; +import { HasSystemsCardProps } from './components/HasSystemsCard'; +import { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard'; +/** @public */ export const catalogPlugin = createPlugin({ id: 'catalog', apis: [ @@ -62,16 +74,19 @@ export const catalogPlugin = createPlugin({ }, }); -export const CatalogIndexPage = catalogPlugin.provide( - createRoutableExtension({ - name: 'CatalogIndexPage', - component: () => - import('./components/CatalogPage').then(m => m.CatalogPage), - mountPoint: catalogRouteRef, - }), -); +/** @public */ +export const CatalogIndexPage: (props: DefaultCatalogPageProps) => JSX.Element = + catalogPlugin.provide( + createRoutableExtension({ + name: 'CatalogIndexPage', + component: () => + import('./components/CatalogPage').then(m => m.CatalogPage), + mountPoint: catalogRouteRef, + }), + ); -export const CatalogEntityPage = catalogPlugin.provide( +/** @public */ +export const CatalogEntityPage: () => JSX.Element = catalogPlugin.provide( createRoutableExtension({ name: 'CatalogEntityPage', component: () => @@ -80,15 +95,18 @@ export const CatalogEntityPage = catalogPlugin.provide( }), ); -export const EntityAboutCard = catalogPlugin.provide( - createComponentExtension({ - name: 'EntityAboutCard', - component: { - lazy: () => import('./components/AboutCard').then(m => m.AboutCard), - }, - }), -); +/** @public */ +export const EntityAboutCard: (props: AboutCardProps) => JSX.Element = + catalogPlugin.provide( + createComponentExtension({ + name: 'EntityAboutCard', + component: { + lazy: () => import('./components/AboutCard').then(m => m.AboutCard), + }, + }), + ); +/** @public */ export const EntityLinksCard = catalogPlugin.provide( createComponentExtension({ name: 'EntityLinksCard', @@ -99,17 +117,22 @@ export const EntityLinksCard = catalogPlugin.provide( }), ); -export const EntityHasSystemsCard = catalogPlugin.provide( - createComponentExtension({ - name: 'EntityHasSystemsCard', - component: { - lazy: () => - import('./components/HasSystemsCard').then(m => m.HasSystemsCard), - }, - }), -); +/** @public */ +export const EntityHasSystemsCard: (props: HasSystemsCardProps) => JSX.Element = + catalogPlugin.provide( + createComponentExtension({ + name: 'EntityHasSystemsCard', + component: { + lazy: () => + import('./components/HasSystemsCard').then(m => m.HasSystemsCard), + }, + }), + ); -export const EntityHasComponentsCard = catalogPlugin.provide( +/** @public */ +export const EntityHasComponentsCard: ( + props: HasComponentsCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityHasComponentsCard', component: { @@ -119,7 +142,10 @@ export const EntityHasComponentsCard = catalogPlugin.provide( }), ); -export const EntityHasSubcomponentsCard = catalogPlugin.provide( +/** @public */ +export const EntityHasSubcomponentsCard: ( + props: HasSubcomponentsCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityHasSubcomponentsCard', component: { @@ -131,7 +157,10 @@ export const EntityHasSubcomponentsCard = catalogPlugin.provide( }), ); -export const EntityHasResourcesCard = catalogPlugin.provide( +/** @public */ +export const EntityHasResourcesCard: ( + props: HasResourcesCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityHasResourcesCard', component: { @@ -141,7 +170,10 @@ export const EntityHasResourcesCard = catalogPlugin.provide( }), ); -export const EntityDependsOnComponentsCard = catalogPlugin.provide( +/** @public */ +export const EntityDependsOnComponentsCard: ( + props: DependsOnComponentsCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityDependsOnComponentsCard', component: { @@ -153,7 +185,10 @@ export const EntityDependsOnComponentsCard = catalogPlugin.provide( }), ); -export const EntityDependencyOfComponentsCard = catalogPlugin.provide( +/** @public */ +export const EntityDependencyOfComponentsCard: ( + props: DependencyOfComponentsCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityDependencyOfComponentsCard', component: { @@ -165,7 +200,10 @@ export const EntityDependencyOfComponentsCard = catalogPlugin.provide( }), ); -export const EntityDependsOnResourcesCard = catalogPlugin.provide( +/** @public */ +export const EntityDependsOnResourcesCard: ( + props: DependsOnResourcesCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'EntityDependsOnResourcesCard', component: { @@ -177,21 +215,10 @@ export const EntityDependsOnResourcesCard = catalogPlugin.provide( }), ); -/** - * @deprecated This component is replaced by EntityCatalogGraphCard which is imported from `@backstage/plugin-catalog-graph`. This component will be removed in an - * upcoming release - */ -export const EntitySystemDiagramCard = catalogPlugin.provide( - createComponentExtension({ - name: 'EntitySystemDiagramCard', - component: { - lazy: () => - import('./components/SystemDiagramCard').then(m => m.SystemDiagramCard), - }, - }), -); - -export const RelatedEntitiesCard = catalogPlugin.provide( +/** @public */ +export const RelatedEntitiesCard: ( + props: RelatedEntitiesCardProps, +) => JSX.Element = catalogPlugin.provide( createComponentExtension({ name: 'RelatedEntitiesCard', component: { diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 7258ea0570..bf1066ff5d 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cicd-statistics +## 0.1.1 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 0b9bce831b: Updated `@backstage/core-plugin-api` dependency. +- Updated dependencies + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index de221887c8..3738db43db 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.0", + "version": "0.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,22 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "devDependencies": { "@types/react": "^16.13.1 || ^17.0.0", "@types/luxon": "^2.0.5" }, "dependencies": { - "@backstage/catalog-model": "^0.9.8", - "@backstage/core-plugin-api": "^0.4.1", - "@backstage/plugin-catalog-react": "^0.6.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", "@date-io/luxon": "^1.3.13", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.11.2", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index fcd6237d70..e3bbd6c78d 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-circleci +## 0.2.38 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.37 ### Patch Changes diff --git a/plugins/circleci/api-report.md b/plugins/circleci/api-report.md index bb4334c0f9..5cdf916514 100644 --- a/plugins/circleci/api-report.md +++ b/plugins/circleci/api-report.md @@ -87,9 +87,7 @@ export const circleCIRouteRef: RouteRef; // Warning: (ae-missing-release-tag) "EntityCircleCIContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityCircleCIContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityCircleCIContent: () => JSX.Element; export { GitType }; @@ -100,9 +98,8 @@ const isCircleCIAvailable: (entity: Entity) => boolean; export { isCircleCIAvailable }; export { isCircleCIAvailable as isPluginApplicableToEntity }; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (_props: Props) => JSX.Element; +export const Router: () => JSX.Element; ``` diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 58df662e68..92db23a09f 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.2.37", + "version": "0.2.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,21 +25,21 @@ "circleci" ], "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "clean": "backstage-cli clean", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", "diff": "backstage-cli plugin:diff", - "start": "backstage-cli plugin:serve", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack" + "start": "backstage-cli package start", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -52,10 +55,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/circleci/src/components/Router.tsx b/plugins/circleci/src/components/Router.tsx index 5aa8dd9df9..e16c91f2a0 100644 --- a/plugins/circleci/src/components/Router.tsx +++ b/plugins/circleci/src/components/Router.tsx @@ -27,12 +27,7 @@ import { MissingAnnotationEmptyState } from '@backstage/core-components'; export const isCircleCIAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[CIRCLECI_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; - -export const Router = (_props: Props) => { +export const Router = () => { const { entity } = useEntity(); if (!isCircleCIAvailable(entity)) { diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 8a434df33d..cd5ec88d36 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-cloudbuild +## 0.2.36 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.35 ### Patch Changes diff --git a/plugins/cloudbuild/api-report.md b/plugins/cloudbuild/api-report.md index fefa4fe344..4077a8991a 100644 --- a/plugins/cloudbuild/api-report.md +++ b/plugins/cloudbuild/api-report.md @@ -149,9 +149,7 @@ export { cloudbuildPlugin as plugin }; // Warning: (ae-missing-release-tag) "EntityCloudbuildContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityCloudbuildContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityCloudbuildContent: () => JSX.Element; // Warning: (ae-missing-release-tag) "EntityLatestCloudbuildRunCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -159,7 +157,6 @@ export const EntityCloudbuildContent: (_props: { export const EntityLatestCloudbuildRunCard: ({ branch, }: { - entity?: Entity | undefined; branch: string; }) => JSX.Element; @@ -169,7 +166,6 @@ export const EntityLatestCloudbuildRunCard: ({ export const EntityLatestCloudbuildsForBranchCard: ({ branch, }: { - entity?: Entity | undefined; branch: string; }) => JSX.Element; @@ -196,7 +192,6 @@ export { isCloudbuildAvailable as isPluginApplicableToEntity }; export const LatestWorkflowRunCard: ({ branch, }: { - entity?: Entity | undefined; branch: string; }) => JSX.Element; @@ -206,7 +201,6 @@ export const LatestWorkflowRunCard: ({ export const LatestWorkflowsForBranchCard: ({ branch, }: { - entity?: Entity | undefined; branch: string; }) => JSX.Element; @@ -256,11 +250,10 @@ export interface Results { buildStepOutputs: string[]; } -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (_props: Props) => JSX.Element; +export const Router: () => JSX.Element; // Warning: (ae-missing-release-tag) "Source" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 7ed6f48f71..ed8641db50 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.2.35", + "version": "0.2.36", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,21 @@ "google cloud" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cloudbuild/src/components/Cards/Cards.tsx b/plugins/cloudbuild/src/components/Cards/Cards.tsx index dad1f7d38f..82e0eb1b88 100644 --- a/plugins/cloudbuild/src/components/Cards/Cards.tsx +++ b/plugins/cloudbuild/src/components/Cards/Cards.tsx @@ -16,7 +16,6 @@ import React, { useEffect } from 'react'; import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunsTable } from '../WorkflowRunsTable'; -import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { Theme, makeStyles, LinearProgress } from '@material-ui/core'; @@ -76,8 +75,6 @@ const WidgetContent = ({ export const LatestWorkflowRunCard = ({ branch = 'master', }: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; branch: string; }) => { const { entity } = useEntity(); @@ -109,8 +106,6 @@ export const LatestWorkflowRunCard = ({ export const LatestWorkflowsForBranchCard = ({ branch = 'master', }: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; branch: string; }) => { const { entity } = useEntity(); diff --git a/plugins/cloudbuild/src/components/Router.tsx b/plugins/cloudbuild/src/components/Router.tsx index bdeae7e8fd..e4c590bcaf 100644 --- a/plugins/cloudbuild/src/components/Router.tsx +++ b/plugins/cloudbuild/src/components/Router.tsx @@ -26,12 +26,7 @@ import { MissingAnnotationEmptyState } from '@backstage/core-components'; export const isCloudbuildAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[CLOUDBUILD_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; - -export const Router = (_props: Props) => { +export const Router = () => { const { entity } = useEntity(); if (!isCloudbuildAvailable(entity)) { diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 5e0bbb0c0f..768b3c9be2 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-code-coverage-backend +## 0.1.24 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + +## 0.1.23 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.1.22 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index c5c77f9873..29e11ff2b6 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.1.22", + "version": "0.1.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,22 +10,25 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -36,7 +39,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 2fc3acda84..0d3f1ba79e 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-code-coverage +## 0.1.26 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.1.25 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 49f092bf25..3e7740805e 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.1.25", + "version": "0.1.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,24 +10,27 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +46,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index a8b6f14292..237991ef8e 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-config-schema +## 0.1.22 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + ## 0.1.21 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 46e030dbc8..88440e73d7 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.21", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,23 +10,26 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -38,10 +41,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index e1f3caf8ec..966c3a13e2 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-cost-insights +## 0.11.21 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.11.20 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 45178cb475..344fcd58ce 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.11.20", + "version": "0.11.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,21 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -57,10 +60,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cost-insights/src/hooks/useGroups.tsx b/plugins/cost-insights/src/hooks/useGroups.tsx index 6d20f435b3..de0e253763 100644 --- a/plugins/cost-insights/src/hooks/useGroups.tsx +++ b/plugins/cost-insights/src/hooks/useGroups.tsx @@ -26,10 +26,7 @@ import { MapLoadingToProps, useLoading } from './useLoading'; import { Group, Maybe } from '../types'; import { DefaultLoadingAction } from '../utils/loading'; import { useApi, identityApiRef } from '@backstage/core-plugin-api'; -import { - ENTITY_DEFAULT_NAMESPACE, - parseEntityRef, -} from '@backstage/catalog-model'; +import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; type GroupsProviderLoadingProps = { dispatchLoadingGroups: (isLoading: boolean) => void; @@ -66,7 +63,7 @@ export const GroupsProvider = ({ children }: PropsWithChildren<{}>) => { const { userEntityRef } = await identityApi.getBackstageIdentity(); const { name: userId } = parseEntityRef(userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }); const g = await client.getUserGroups(userId); setGroups(g); diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index b546ab7408..ae74a864e1 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-explore-react +## 0.0.12 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-plugin-api@0.6.1 + ## 0.0.11 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 3da9de5e08..c47622540d 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.11", + "version": "0.0.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,20 +24,21 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "clean": "backstage-cli clean", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-plugin-api": "^0.6.0" + "@backstage/core-plugin-api": "^0.6.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/dev-utils": "^0.2.21-next.0", - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/cli": "^0.14.0", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index d417976d1c..6c484d1c8f 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-explore +## 0.3.30 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/plugin-explore-react@0.0.12 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.3.29 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 7cb22f5782..3b83e42bca 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.3.29", + "version": "0.3.30", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,22 +24,22 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "clean": "backstage-cli clean", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "start": "backstage-cli plugin:serve" + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-explore-react": "^0.0.11", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-explore-react": "^0.0.12", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx b/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx index d10c262357..53b225daaf 100644 --- a/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx +++ b/plugins/explore/src/components/DefaultExplorePage/DefaultExplorePage.test.tsx @@ -24,14 +24,14 @@ describe('', () => { const catalogApi: jest.Mocked = { addLocation: jest.fn(_a => new Promise(() => {})), getEntities: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), getEntityByName: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( diff --git a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx index e36bd4ddb9..1310d9f31e 100644 --- a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx +++ b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.test.tsx @@ -25,14 +25,14 @@ describe('', () => { const catalogApi: jest.Mocked = { addLocation: jest.fn(_a => new Promise(() => {})), getEntities: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), getEntityByName: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx index 5d3f7c358b..255db061aa 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsExplorerContent.test.tsx @@ -25,14 +25,14 @@ describe('', () => { const catalogApi: jest.Mocked = { addLocation: jest.fn(_a => new Promise(() => {})), getEntities: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), getEntityByName: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const Wrapper = ({ children }: { children?: React.ReactNode }) => ( diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index e446663842..f2a5147e2a 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-firehydrant +## 0.1.16 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 3a2a893df6: chore(deps): bump `luxon` from 2.0.2 to 2.3.0 +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/theme@0.2.15 + ## 0.1.15 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 81272e2b6d..e5acb5bf75 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.15", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,35 +11,38 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "luxon": "^1.27.0", + "luxon": "^2.0.2", "react-use": "^17.2.4" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 6e42e95021..53cebb5eb0 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-fossa +## 0.2.31 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.30 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 53e40aae96..5cfbf63128 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.30", + "version": "0.2.31", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,22 +25,22 @@ "fossa" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx index 421ff4431f..2759afd585 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx @@ -30,13 +30,13 @@ describe('', () => { addLocation: jest.fn(), getEntities: jest.fn(), getEntityByName: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), - getOriginLocationByEntity: jest.fn(), removeEntityByUid: jest.fn(), removeLocationById: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; const fossaApi: jest.Mocked = { getFindingSummary: jest.fn(), diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 80761a4736..8ddb89dca7 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gcp-projects +## 0.3.18 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- e242726f78: Switches to use react-hookz in place of react-use. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.3.17 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 992336300f..869f6016ea 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.17", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,33 +24,33 @@ "google cloud" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "react-router-dom": "6.0.0-beta.0", - "react-use": "^17.2.4" + "@react-hookz/web": "^12.3.0" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx b/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx index 36247ac492..b900b81695 100644 --- a/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx +++ b/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx @@ -27,7 +27,7 @@ import { Typography, } from '@material-ui/core'; import React from 'react'; -import useAsync from 'react-use/lib/useAsync'; +import { useAsync, useMountEffect } from '@react-hookz/web'; import { gcpApiRef } from '../../api'; import { @@ -60,19 +60,13 @@ const DetailsPage = () => { const api = useApi(gcpApiRef); const classes = useStyles(); - const { - loading, - error, - value: details, - } = useAsync( - async () => - api.getProject( - decodeURIComponent(location.search.split('projectId=')[1]), - ), - [location.search], + const [{ status, result: details, error }, { execute }] = useAsync(async () => + api.getProject(decodeURIComponent(location.search.split('projectId=')[1])), ); - if (loading) { + useMountEffect(execute); + + if (status === 'loading') { return ; } else if (error) { return ( diff --git a/plugins/gcp-projects/src/components/ProjectListPage/ProjectListPage.tsx b/plugins/gcp-projects/src/components/ProjectListPage/ProjectListPage.tsx index d5a57432b3..dea12f4b60 100644 --- a/plugins/gcp-projects/src/components/ProjectListPage/ProjectListPage.tsx +++ b/plugins/gcp-projects/src/components/ProjectListPage/ProjectListPage.tsx @@ -18,7 +18,7 @@ import { Button, LinearProgress, Tooltip, Typography } from '@material-ui/core'; import React from 'react'; -import useAsync from 'react-use/lib/useAsync'; +import { useAsync, useMountEffect } from '@react-hookz/web'; import { gcpApiRef, Project } from '../../api'; import { @@ -58,9 +58,12 @@ const labels = ( const PageContents = () => { const api = useApi(gcpApiRef); - const { loading, error, value } = useAsync(() => api.listProjects()); + const [{ status, result, error }, { execute }] = useAsync(() => + api.listProjects(), + ); + useMountEffect(execute); - if (loading) { + if (status === 'loading') { return ; } else if (error) { return ( @@ -108,7 +111,7 @@ const PageContents = () => { }, ]} data={ - value?.map((project: Project) => ({ + result?.map((project: Project) => ({ id: project.projectId, name: project.name, projectNumber: project?.projectNumber || 'Error', diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index db988dbc9b..c6056e2007 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-git-release-manager +## 0.3.12 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration@0.7.3 + - @backstage/theme@0.2.15 + ## 0.3.11 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 381ca0dd24..1df9e8005a 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.11", + "version": "0.3.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,21 +10,24 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration": "^0.7.2", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/integration": "^0.7.3", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 2399292e8d..fc41232974 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-github-actions +## 0.4.36 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 7efee0f94c: Fixed an issue where an error message was being displayed on the initial component render. This was due to values owner/repo not yet being set. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/integration@0.7.3 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.4.35 ### Patch Changes diff --git a/plugins/github-actions/api-report.md b/plugins/github-actions/api-report.md index fcb3209fb9..ee3e1d679d 100644 --- a/plugins/github-actions/api-report.md +++ b/plugins/github-actions/api-report.md @@ -31,9 +31,7 @@ export enum BuildStatus { // Warning: (ae-missing-release-tag) "EntityGithubActionsContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityGithubActionsContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityGithubActionsContent: () => JSX.Element; // Warning: (ae-missing-release-tag) "EntityLatestGithubActionRunCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -42,7 +40,6 @@ export const EntityLatestGithubActionRunCard: ({ branch, variant, }: { - entity?: Entity | undefined; branch: string; variant?: InfoCardVariants | undefined; }) => JSX.Element; @@ -54,7 +51,6 @@ export const EntityLatestGithubActionsForBranchCard: ({ branch, variant, }: { - entity?: Entity | undefined; branch: string; variant?: InfoCardVariants | undefined; }) => JSX.Element; @@ -315,7 +311,7 @@ export type Jobs = { export const LatestWorkflowRunCard: ({ branch, variant, -}: Props_3) => JSX.Element; +}: Props_2) => JSX.Element; // Warning: (ae-missing-release-tag) "LatestWorkflowsForBranchCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -323,7 +319,7 @@ export const LatestWorkflowRunCard: ({ export const LatestWorkflowsForBranchCard: ({ branch, variant, -}: Props_3) => JSX.Element; +}: Props_2) => JSX.Element; // Warning: (ae-missing-release-tag) "RecentWorkflowRunsCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -335,11 +331,10 @@ export const RecentWorkflowRunsCard: ({ variant, }: Props) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (_props: Props_2) => JSX.Element; +export const Router: () => JSX.Element; // Warning: (ae-missing-release-tag) "Step" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index cb112fedb1..182202dfb3 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.4.35", + "version": "0.4.36", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -23,22 +26,22 @@ "github actions" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -52,10 +55,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/github-actions/src/components/Cards/Cards.tsx b/plugins/github-actions/src/components/Cards/Cards.tsx index cb4b2190fc..61a5146bee 100644 --- a/plugins/github-actions/src/components/Cards/Cards.tsx +++ b/plugins/github-actions/src/components/Cards/Cards.tsx @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; import { @@ -24,7 +23,7 @@ import { } from '@material-ui/core'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import React, { useEffect } from 'react'; -import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName'; +import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity'; import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunsTable } from '../WorkflowRunsTable'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; @@ -122,8 +121,6 @@ export const LatestWorkflowRunCard = ({ }; type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; branch: string; variant?: InfoCardVariants; }; diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 0f9573e051..a987a8569f 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -75,7 +75,7 @@ describe('', () => { jest.resetAllMocks(); }); - const renderSubject = (props: RecentWorkflowRunsCardProps = { entity }) => + const renderSubject = (props: RecentWorkflowRunsCardProps = {}) => render( @@ -85,7 +85,7 @@ describe('', () => { [configApiRef, configApi], ]} > - + @@ -113,7 +113,7 @@ describe('', () => { it('requests only the required number of workflow runs', async () => { const limit = 3; - renderSubject({ entity, limit }); + renderSubject({ limit }); expect(useWorkflowRuns).toHaveBeenCalledWith( expect.objectContaining({ initialPageSize: limit }), ); @@ -128,7 +128,7 @@ describe('', () => { it('filters workflows by branch if one is specified', async () => { const branch = 'master'; - renderSubject({ entity, branch }); + renderSubject({ branch }); expect(useWorkflowRuns).toHaveBeenCalledWith( expect.objectContaining({ branch }), ); diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index 3423bea84d..4e37a2b19b 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; import React, { useEffect } from 'react'; import { generatePath, Link as RouterLink } from 'react-router-dom'; -import { GITHUB_ACTIONS_ANNOTATION } from '../useProjectName'; +import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity'; import { useWorkflowRuns } from '../useWorkflowRuns'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { Typography } from '@material-ui/core'; @@ -34,8 +33,6 @@ import { const firstLine = (message: string): string => message.split('\n')[0]; export type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; branch?: string; dense?: boolean; limit?: number; diff --git a/plugins/github-actions/src/components/Router.tsx b/plugins/github-actions/src/components/Router.tsx index ea07213c45..793293cce8 100644 --- a/plugins/github-actions/src/components/Router.tsx +++ b/plugins/github-actions/src/components/Router.tsx @@ -20,18 +20,13 @@ import { Routes, Route } from 'react-router'; import { buildRouteRef } from '../routes'; import { WorkflowRunDetails } from './WorkflowRunDetails'; import { WorkflowRunsTable } from './WorkflowRunsTable'; -import { GITHUB_ACTIONS_ANNOTATION } from './useProjectName'; +import { GITHUB_ACTIONS_ANNOTATION } from './getProjectNameFromEntity'; import { MissingAnnotationEmptyState } from '@backstage/core-components'; export const isGithubActionsAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; - -export const Router = (_props: Props) => { +export const Router = () => { const { entity } = useEntity(); if (!isGithubActionsAvailable(entity)) { diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index aebf7dfa01..989ab27800 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -39,7 +39,7 @@ import ExternalLinkIcon from '@material-ui/icons/Launch'; import { DateTime } from 'luxon'; import React from 'react'; import { Job, Jobs, Step } from '../../api'; -import { useProjectName } from '../useProjectName'; +import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { useWorkflowRunJobs } from './useWorkflowRunJobs'; import { useWorkflowRunsDetails } from './useWorkflowRunsDetails'; @@ -164,25 +164,25 @@ const JobsList = ({ jobs, entity }: { jobs?: Jobs; entity: Entity }) => { export const WorkflowRunDetails = ({ entity }: { entity: Entity }) => { const config = useApi(configApiRef); - const projectName = useProjectName(entity); + const projectName = getProjectNameFromEntity(entity); // TODO: Get github hostname from metadata annotation const hostname = readGitHubIntegrationConfigs( config.getOptionalConfigArray('integrations.github') ?? [], )[0].host; - const [owner, repo] = projectName.value ? projectName.value.split('/') : []; + const [owner, repo] = (projectName && projectName.split('/')) || []; const details = useWorkflowRunsDetails({ hostname, owner, repo }); const jobs = useWorkflowRunJobs({ hostname, owner, repo }); - const error = projectName.error || (projectName.value && details.error); const classes = useStyles(); - if (error) { + + if (details.error && details.error.message) { return ( - Failed to load build, {error.message} + Failed to load build, {details.error.message} ); - } else if (projectName.loading || details.loading) { + } else if (details.loading) { return ; } return ( diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunJobs.ts b/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunJobs.ts index 002d379ed1..ba0f3b6ba8 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunJobs.ts +++ b/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunJobs.ts @@ -37,7 +37,7 @@ export const useWorkflowRunJobs = ({ repo, id: parseInt(id, 10), }) - : Promise.reject('No repo/owner provided'); + : Promise.reject(new Error('No repo/owner provided')); }, [repo, owner, id]); return jobs; }; diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunsDetails.ts b/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunsDetails.ts index ef9b4f7ccf..10a043161e 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunsDetails.ts +++ b/plugins/github-actions/src/components/WorkflowRunDetails/useWorkflowRunsDetails.ts @@ -37,7 +37,7 @@ export const useWorkflowRunsDetails = ({ repo, id: parseInt(id, 10), }) - : Promise.reject('No repo/owner provided'); + : Promise.reject(new Error('No repo/owner provided')); }, [repo, owner, id]); return details; }; diff --git a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx index 0f1670bbbc..bf66399288 100644 --- a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx +++ b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx @@ -33,7 +33,7 @@ import { import DescriptionIcon from '@material-ui/icons/Description'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import React from 'react'; -import { useProjectName } from '../useProjectName'; +import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { useDownloadWorkflowRunLogs } from './useDownloadWorkflowRunLogs'; const useStyles = makeStyles(theme => ({ @@ -77,13 +77,13 @@ export const WorkflowRunLogs = ({ }) => { const config = useApi(configApiRef); const classes = useStyles(); - const projectName = useProjectName(entity); + const projectName = getProjectNameFromEntity(entity); // TODO: Get github hostname from metadata annotation const hostname = readGitHubIntegrationConfigs( config.getOptionalConfigArray('integrations.github') ?? [], )[0].host; - const [owner, repo] = projectName.value ? projectName.value.split('/') : []; + const [owner, repo] = (projectName && projectName.split('/')) || []; const jobLogs = useDownloadWorkflowRunLogs({ hostname, owner, diff --git a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx index 81fa036221..c8c42eb1bc 100644 --- a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx +++ b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx @@ -29,7 +29,7 @@ import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import SyncIcon from '@material-ui/icons/Sync'; import { buildRouteRef } from '../../routes'; -import { useProjectName } from '../useProjectName'; +import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { Entity } from '@backstage/catalog-model'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; @@ -157,7 +157,7 @@ export const WorkflowRunsTable = ({ branch?: string; }) => { const config = useApi(configApiRef); - const { value: projectName, loading } = useProjectName(entity); + const projectName = getProjectNameFromEntity(entity); // TODO: Get github hostname from metadata annotation const hostname = readGitHubIntegrationConfigs( config.getOptionalConfigArray('integrations.github') ?? [], @@ -172,7 +172,7 @@ export const WorkflowRunsTable = ({ }); const githubHost = hostname || 'github.com'; - const hasNoRuns = !loading && !tableProps.loading && !runs; + const hasNoRuns = !tableProps.loading && !runs; return hasNoRuns ? ( { - const { value, loading, error } = useAsync(async () => { - return entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? ''; - }); - return { value, loading, error }; -}; +export const getProjectNameFromEntity = (entity: Entity) => + entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? ''; diff --git a/plugins/github-actions/src/index.ts b/plugins/github-actions/src/index.ts index f520b9fbbc..ab041b4970 100644 --- a/plugins/github-actions/src/index.ts +++ b/plugins/github-actions/src/index.ts @@ -35,4 +35,4 @@ export { isGithubActionsAvailable as isPluginApplicableToEntity, } from './components/Router'; export * from './components/Cards'; -export { GITHUB_ACTIONS_ANNOTATION } from './components/useProjectName'; +export { GITHUB_ACTIONS_ANNOTATION } from './components/getProjectNameFromEntity'; diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 8bcaa8287f..90662a2e55 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-github-deployments +## 0.1.30 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.1.29 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index e4c3e4917c..612e9dc00b 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.29", + "version": "0.1.30", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,25 +10,28 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -40,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/github-deployments/src/api/index.ts b/plugins/github-deployments/src/api/index.ts index b64d914612..48363557ff 100644 --- a/plugins/github-deployments/src/api/index.ts +++ b/plugins/github-deployments/src/api/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { parseLocationReference } from '@backstage/catalog-model'; +import { parseLocationRef } from '@backstage/catalog-model'; import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { graphql } from '@octokit/graphql'; @@ -27,8 +27,8 @@ const getBaseUrl = ( return 'https://api.github.com'; } - const location = parseLocationReference(host); - if (location.type !== 'github' && location.type !== 'url') { + const location = parseLocationRef(host); + if (location.type !== 'url') { return 'https://api.github.com'; } diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index dba5bbfe1c..dedd2c3082 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -254,7 +254,7 @@ describe('github-deployments', () => { entity.entity.metadata.annotations = { 'github.com/project-slug': 'org/repo', 'backstage.io/source-location': - 'github:https://my-github-1.com/org/repo/tree/master/', + 'url:https://my-github-1.com/org/repo/tree/master/', }; }); @@ -276,7 +276,7 @@ describe('github-deployments', () => { entity.entity.metadata.annotations = { 'github.com/project-slug': 'org/repo', 'backstage.io/managed-by-location': - 'github:https://my-github-2.com/org/repo/blob/master/catalog-info.yaml', + 'url:https://my-github-2.com/org/repo/blob/master/catalog-info.yaml', }; }); @@ -298,7 +298,7 @@ describe('github-deployments', () => { entity.entity.metadata.annotations = { 'github.com/project-slug': 'org/repo', 'backstage.io/managed-by-location': - 'github:https://my-github-3.com/org/repo/blob/master/catalog-info.yaml', + 'url:https://my-github-3.com/org/repo/blob/master/catalog-info.yaml', }; }); @@ -323,7 +323,7 @@ describe('github-deployments', () => { entity.entity.metadata.annotations = { 'github.com/project-slug': 'org/repo', 'backstage.io/managed-by-location': - 'github:https://my-github-unknown.com/org/repo/blob/master/catalog-info.yaml', + 'url:https://my-github-unknown.com/org/repo/blob/master/catalog-info.yaml', }; }); diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx index 901e20a899..68881617f4 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx @@ -23,8 +23,8 @@ import { } from '../Router'; import { GithubDeploymentsTable } from './GithubDeploymentsTable/GithubDeploymentsTable'; import { - LOCATION_ANNOTATION, - SOURCE_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + ANNOTATION_SOURCE_LOCATION, } from '@backstage/catalog-model'; import { @@ -88,8 +88,8 @@ export const GithubDeploymentsCard = (props: { const { last, lastStatuses, columns } = props; const { entity } = useEntity(); const [host] = [ - entity?.metadata.annotations?.[SOURCE_LOCATION_ANNOTATION], - entity?.metadata.annotations?.[LOCATION_ANNOTATION], + entity?.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION], + entity?.metadata.annotations?.[ANNOTATION_LOCATION], ].filter(Boolean); return !isGithubDeploymentsAvailable(entity) ? ( diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index edf8bec0ae..9e193137e6 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-gitops-profiles +## 0.3.17 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.3.16 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 1cadbc8d65..4720f1bd2e 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.16", + "version": "0.3.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,19 +25,19 @@ "gitops" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -45,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index b2e5024fea..2061eb66f1 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-gocd +## 0.1.5 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.1.4 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 86802a43f2..f4879509a0 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.4", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -18,22 +21,22 @@ "directory": "plugins/gocd" }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -46,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index da7919fb5e..fb4d0e7274 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-graphiql +## 0.2.31 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.2.30 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 185e273c3f..23cd34bccc 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,13 +1,16 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.30", + "version": "0.2.31", "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://github.com/backstage/backstage/tree/master/plugins/graphiql#readme", "repository": { "type": "git", @@ -21,19 +24,19 @@ "main": "src/index.ts", "types": "src/index.ts", "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -45,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 749ced2527..f1908e2f77 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-graphql-backend +## 0.1.16 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/plugin-catalog-graphql@0.3.3 + +## 0.1.15 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/plugin-catalog-graphql@0.3.2 + - @backstage/config@0.1.14 + ## 0.1.14 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index a13a901646..061ba58544 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,18 +25,18 @@ "graphql" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/plugin-catalog-graphql": "^0.3.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/plugin-catalog-graphql": "^0.3.2", "@graphql-tools/schema": "^8.3.1", "graphql-modules": "^1.0.0", "@types/express": "^4.17.6", @@ -42,13 +45,13 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "graphql": "^16.0.0", - "helmet": "^4.0.0", + "helmet": "^5.0.2", "reflect-metadata": "^0.1.13", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.35.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index d0c0a5bb44..f1d42bd790 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-home +## 0.4.15 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 651b919dbb: Add Renderer support for the HomePageToolkit component. + + Previously `` would + result in the error `can't access property "map", props.tools is undefined`. + This change adds a context that can pass props down to the HomePageToolkit. + Also introduced is an `expanded` prop on the `ComponentAccordion` to setting + the default expanded state. See `In Accordian` story for details. + +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/plugin-search@0.7.0 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.4.14 ### Patch Changes diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 264189ee07..6fae50151c 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -24,6 +24,7 @@ export type ClockConfig = { // @public (undocumented) export const ComponentAccordion: ({ title, + expanded, Content, Actions, Settings, @@ -31,6 +32,7 @@ export const ComponentAccordion: ({ ...childProps }: { title: string; + expanded?: boolean | undefined; Content: () => JSX.Element; Actions?: (() => JSX.Element) | undefined; Settings?: (() => JSX.Element) | undefined; diff --git a/plugins/home/package.json b/plugins/home/package.json index f57b0bb83e..7c63b4c645 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.14", + "version": "0.4.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,23 +10,36 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, + "homepage": "https://github.com/backstage/backstage/tree/master/plugins/home#readme", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/home" + }, + "keywords": [ + "backstage", + "homepage" + ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-search": "^0.6.2", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-search": "^0.7.0", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/home/src/componentRenderers/ComponentAccordion.tsx b/plugins/home/src/componentRenderers/ComponentAccordion.tsx index 5cf54d7a0c..ef44f7f292 100644 --- a/plugins/home/src/componentRenderers/ComponentAccordion.tsx +++ b/plugins/home/src/componentRenderers/ComponentAccordion.tsx @@ -33,10 +33,14 @@ const useStyles = makeStyles((theme: Theme) => ({ settingsIconButton: { padding: theme.spacing(0, 1, 0, 0), }, + contentContainer: { + width: '100%', + }, })); export const ComponentAccordion = ({ title, + expanded = false, Content, Actions, Settings, @@ -44,6 +48,7 @@ export const ComponentAccordion = ({ ...childProps }: { title: string; + expanded?: boolean; Content: () => JSX.Element; Actions?: () => JSX.Element; Settings?: () => JSX.Element; @@ -51,7 +56,7 @@ export const ComponentAccordion = ({ }) => { const classes = useStyles(); const [settingsIsExpanded, setSettingsIsExpanded] = React.useState(false); - const [isExpanded, setIsExpanded] = React.useState(false); + const [isExpanded, setIsExpanded] = React.useState(expanded); const handleOpenSettings = (e: any) => { e.stopPropagation(); @@ -71,7 +76,9 @@ export const ComponentAccordion = ({ )} setIsExpanded(expanded)} + onChange={(_e: any, expandedValue: boolean) => + setIsExpanded(expandedValue) + } > }> {Settings && ( @@ -85,7 +92,7 @@ export const ComponentAccordion = ({ {title} -
+
{Actions && }
diff --git a/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx b/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx index 7fbaff08f9..1955019a4a 100644 --- a/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx +++ b/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx @@ -13,19 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { renderInTestApp } from '@backstage/test-utils'; import React from 'react'; import { Content } from './Content'; +import { ContextProvider } from './Context'; describe('', () => { + const tools = [ + { label: 'tool', url: '/url', icon:
icon
}, + { label: 'tool 2', url: '/url-2', icon:
icon 2
}, + ]; + test('should render list of tools', async () => { + const { getByText } = await renderInTestApp(); + + expect(getByText('tool')).toBeInTheDocument(); + expect(getByText('tool 2')).toBeInTheDocument(); + expect(getByText('tool').closest('a')).toHaveAttribute('href', '/url'); + expect(getByText('tool 2').closest('a')).toHaveAttribute('href', '/url-2'); + }); + + test('should render list of tools using context', async () => { const { getByText } = await renderInTestApp( - icon
}, - { label: 'tool 2', url: '/url-2', icon:
icon 2
}, - ]} - />, + + + , ); expect(getByText('tool')).toBeInTheDocument(); diff --git a/plugins/home/src/homePageComponents/Toolkit/Content.tsx b/plugins/home/src/homePageComponents/Toolkit/Content.tsx index 4ee1884bd0..21affc57f1 100644 --- a/plugins/home/src/homePageComponents/Toolkit/Content.tsx +++ b/plugins/home/src/homePageComponents/Toolkit/Content.tsx @@ -22,6 +22,7 @@ import { ListItemText, } from '@material-ui/core'; import React from 'react'; +import { useToolkit, Tool } from './Context'; const useStyles = makeStyles(theme => ({ toolkit: { @@ -49,12 +50,6 @@ const useStyles = makeStyles(theme => ({ }, })); -type Tool = { - label: string; - url: string; - icon: React.ReactNode; -}; - /** * Props for Toolkit content component {@link Content}. * @@ -71,10 +66,12 @@ export type ToolkitContentProps = { */ export const Content = (props: ToolkitContentProps) => { const classes = useStyles(); + const toolkit = useToolkit(); + const tools = toolkit?.tools ?? props.tools; return ( - {props.tools.map((tool: Tool) => ( + {tools.map((tool: Tool) => ( {tool.icon} (undefined); + +export const ContextProvider = ({ + children, + tools, +}: { + children: JSX.Element; + tools: Tool[]; +}) => { + const [toolsValue, _setTools] = React.useState(tools); + + const value: ToolkitContextValue = { + tools: toolsValue, + }; + + return {children}; +}; + +export const useToolkit = () => { + const value = React.useContext(Context); + return value; +}; + +export default Context; diff --git a/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx b/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx index 0a8e6fffbe..cad188c5d6 100644 --- a/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx +++ b/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx @@ -14,11 +14,13 @@ * limitations under the License. */ -import { TemplateBackstageLogoIcon } from '../../templates'; -import { HomePageToolkit } from '../../plugin'; +import { InfoCard } from '@backstage/core-components'; import { wrapInTestApp } from '@backstage/test-utils'; import { Grid } from '@material-ui/core'; import React, { ComponentType } from 'react'; +import { ComponentAccordion } from '../../componentRenderers'; +import { HomePageToolkit } from '../../plugin'; +import { TemplateBackstageLogoIcon } from '../../templates'; export default { title: 'Plugins/Home/Components/Toolkit', @@ -38,3 +40,43 @@ export const Default = () => { ); }; + +export const InAccordian = () => { + const ExpandedComponentAccordion = (props: any) => ( + + ); + + return ( + + + , + })} + Renderer={ExpandedComponentAccordion} + /> + , + })} + Renderer={ComponentAccordion} + /> + , + })} + Renderer={ComponentAccordion} + /> + + + ); +}; diff --git a/plugins/home/src/homePageComponents/Toolkit/index.ts b/plugins/home/src/homePageComponents/Toolkit/index.ts index 98e0869825..67ea1f3c84 100644 --- a/plugins/home/src/homePageComponents/Toolkit/index.ts +++ b/plugins/home/src/homePageComponents/Toolkit/index.ts @@ -16,3 +16,4 @@ export { Content } from './Content'; export type { ToolkitContentProps } from './Content'; +export { ContextProvider } from './Context'; diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 099110e39f..acd3f6dab0 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-ilert +## 0.1.25 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.1.24 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 4c6581553c..b015836ac1 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.1.24", + "version": "0.1.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,23 +10,26 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -40,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx b/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx index d58fa91108..909e4dc362 100644 --- a/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx +++ b/plugins/ilert/src/components/Incident/IncidentActionsMenu.tsx @@ -27,10 +27,7 @@ import { identityApiRef, } from '@backstage/core-plugin-api'; import { Progress, Link } from '@backstage/core-components'; -import { - ENTITY_DEFAULT_NAMESPACE, - parseEntityRef, -} from '@backstage/catalog-model'; +import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; export const IncidentActionsMenu = ({ incident, @@ -71,7 +68,7 @@ export const IncidentActionsMenu = ({ const { userEntityRef } = await identityApi.getBackstageIdentity(); const { name: userName } = parseEntityRef(userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }); const newIncident = await ilertApi.acceptIncident(incident, userName); alertApi.post({ message: 'Incident accepted.' }); @@ -91,7 +88,7 @@ export const IncidentActionsMenu = ({ const { userEntityRef } = await identityApi.getBackstageIdentity(); const { name: userName } = parseEntityRef(userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }); const newIncident = await ilertApi.resolveIncident(incident, userName); alertApi.post({ message: 'Incident resolved.' }); diff --git a/plugins/ilert/src/components/Incident/IncidentNewModal.tsx b/plugins/ilert/src/components/Incident/IncidentNewModal.tsx index c8f63c6073..561047d45e 100644 --- a/plugins/ilert/src/components/Incident/IncidentNewModal.tsx +++ b/plugins/ilert/src/components/Incident/IncidentNewModal.tsx @@ -14,10 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { - ENTITY_DEFAULT_NAMESPACE, - parseEntityRef, -} from '@backstage/catalog-model'; +import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core/styles'; import Alert from '@material-ui/lab/Alert'; import Button from '@material-ui/core/Button'; @@ -108,7 +105,7 @@ export const IncidentNewModal = ({ const { userEntityRef } = await identityApi.getBackstageIdentity(); const { name: userName } = parseEntityRef(userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }); await ilertApi.createIncident({ integrationKey, diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 17fd3da85a..8639393646 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-jenkins-backend +## 0.1.15 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + +## 0.1.14 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 377fce4677: The `DefaultJenkinsInfoProvider.fromConfig` now requires an implementation of the `CatalogApi` rather than a `CatalogClient` instance. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.1.13 ### Patch Changes diff --git a/plugins/jenkins-backend/api-report.md b/plugins/jenkins-backend/api-report.md index b8d171f9c1..d437a5dd75 100644 --- a/plugins/jenkins-backend/api-report.md +++ b/plugins/jenkins-backend/api-report.md @@ -3,7 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -import { CatalogClient } from '@backstage/catalog-client'; +import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; import express from 'express'; @@ -21,7 +21,7 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider { // (undocumented) static fromConfig(options: { config: Config; - catalog: CatalogClient; + catalog: CatalogApi; }): DefaultJenkinsInfoProvider; // (undocumented) getInstance(opt: { diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 52e8862fae..86ff665900 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.13", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,21 +11,24 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "configSchema": "config.d.ts", "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -34,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", "msw": "^0.35.0", diff --git a/plugins/jenkins-backend/src/service/jenkinsInfoProvider.test.ts b/plugins/jenkins-backend/src/service/jenkinsInfoProvider.test.ts index 496fe535e3..62299926df 100644 --- a/plugins/jenkins-backend/src/service/jenkinsInfoProvider.test.ts +++ b/plugins/jenkins-backend/src/service/jenkinsInfoProvider.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CatalogClient } from '@backstage/catalog-client'; +import { CatalogApi } from '@backstage/catalog-client'; import { Entity, EntityName } from '@backstage/catalog-model'; import { ConfigReader } from '@backstage/config'; import { @@ -159,9 +159,9 @@ describe('JenkinsConfig', () => { }); describe('DefaultJenkinsInfoProvider', () => { - const mockCatalog: jest.Mocked = { + const mockCatalog: jest.Mocked = { getEntityByName: jest.fn(), - } as any as jest.Mocked; + } as any as jest.Mocked; const entityRef: EntityName = { kind: 'Component', diff --git a/plugins/jenkins-backend/src/service/jenkinsInfoProvider.ts b/plugins/jenkins-backend/src/service/jenkinsInfoProvider.ts index 7dbc94dacf..f822f475f1 100644 --- a/plugins/jenkins-backend/src/service/jenkinsInfoProvider.ts +++ b/plugins/jenkins-backend/src/service/jenkinsInfoProvider.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CatalogClient } from '@backstage/catalog-client'; +import { CatalogApi } from '@backstage/catalog-client'; import { Entity, EntityName, @@ -168,12 +168,12 @@ export class DefaultJenkinsInfoProvider implements JenkinsInfoProvider { private constructor( private readonly config: JenkinsConfig, - private readonly catalog: CatalogClient, + private readonly catalog: CatalogApi, ) {} static fromConfig(options: { config: Config; - catalog: CatalogClient; + catalog: CatalogApi; }): DefaultJenkinsInfoProvider { return new DefaultJenkinsInfoProvider( JenkinsConfig.fromConfig(options.config), diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 8611c9d2b7..e5f5ebea46 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-jenkins +## 0.5.21 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.5.20 ### Patch Changes diff --git a/plugins/jenkins/api-report.md b/plugins/jenkins/api-report.md index 61c5327fa1..05ebd1fd03 100644 --- a/plugins/jenkins/api-report.md +++ b/plugins/jenkins/api-report.md @@ -18,9 +18,7 @@ import { RouteRef } from '@backstage/core-plugin-api'; // Warning: (ae-missing-release-tag) "EntityJenkinsContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityJenkinsContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityJenkinsContent: (_props: {}) => JSX.Element; // Warning: (ae-missing-release-tag) "EntityLatestJenkinsRunCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 7b1283cd23..c4cf6a33de 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.5.20", + "version": "0.5.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,22 +25,22 @@ "jenkins" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/jenkins/src/components/Router.tsx b/plugins/jenkins/src/components/Router.tsx index 0d38fe009a..b3561be2b0 100644 --- a/plugins/jenkins/src/components/Router.tsx +++ b/plugins/jenkins/src/components/Router.tsx @@ -27,10 +27,7 @@ export const isJenkinsAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[JENKINS_ANNOTATION]) || Boolean(entity.metadata.annotations?.[LEGACY_JENKINS_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const Router = (_props: Props) => { const { entity } = useEntity(); diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index cd80463672..ba849ba871 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-kafka-backend +## 0.2.19 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + +## 0.2.18 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.2.17 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 01b23ba696..e65540bb5d 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.17", + "version": "0.2.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -23,19 +26,19 @@ ], "configSchema": "config.d.ts", "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -44,7 +47,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/jest-when": "^2.7.2", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index e73c3a6efb..b34c87c416 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kafka +## 0.2.29 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.28 ### Patch Changes diff --git a/plugins/kafka/api-report.md b/plugins/kafka/api-report.md index 0750978b27..95eed1dc13 100644 --- a/plugins/kafka/api-report.md +++ b/plugins/kafka/api-report.md @@ -12,9 +12,7 @@ import { RouteRef } from '@backstage/core-plugin-api'; // Warning: (ae-missing-release-tag) "EntityKafkaContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityKafkaContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityKafkaContent: (_props: {}) => JSX.Element; // Warning: (ae-missing-release-tag) "isPluginApplicableToEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 12dd578daa..a6d57838b5 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.2.28", + "version": "0.2.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,22 +10,25 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -36,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/kafka/src/Router.tsx b/plugins/kafka/src/Router.tsx index c63019253b..133326b5b9 100644 --- a/plugins/kafka/src/Router.tsx +++ b/plugins/kafka/src/Router.tsx @@ -25,10 +25,7 @@ import { MissingAnnotationEmptyState } from '@backstage/core-components'; export const isPluginApplicableToEntity = (entity: Entity) => Boolean(entity.metadata.annotations?.[KAFKA_CONSUMER_GROUP_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const Router = (_props: Props) => { const { entity } = useEntity(); diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 457e17e989..62bf217100 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-kubernetes-backend +## 0.4.9 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/plugin-kubernetes-common@0.2.4 + +## 0.4.8 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 +- fb09a59a3f: Fixed a potential issue in AWS token encoding, where they might not always be properly converted to URL-safe base64. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/plugin-kubernetes-common@0.2.3 + ## 0.4.7 ### Patch Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 9b181c8514..ea273d7632 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -83,15 +83,7 @@ export interface GKEClusterDetails extends ClusterDetails {} export class KubernetesBuilder { constructor(env: KubernetesEnvironment); // (undocumented) - build(): Promise<{ - clusterDetails: ClusterDetails[]; - clusterSupplier: KubernetesClustersSupplier; - customResources: CustomResource[]; - fetcher: KubernetesFetcher; - objectsProvider: KubernetesObjectsProvider; - router: express.Router; - serviceLocator: KubernetesServiceLocator; - }>; + build(): KubernetesBuilderReturn; // (undocumented) protected buildClusterSupplier(): KubernetesClustersSupplier; // (undocumented) @@ -142,6 +134,17 @@ export class KubernetesBuilder { setServiceLocator(serviceLocator?: KubernetesServiceLocator): this; } +// @public +export type KubernetesBuilderReturn = Promise<{ + router: express.Router; + clusterDetails: ClusterDetails[]; + clusterSupplier: KubernetesClustersSupplier; + customResources: CustomResource[]; + fetcher: KubernetesFetcher; + objectsProvider: KubernetesObjectsProvider; + serviceLocator: KubernetesServiceLocator; +}>; + // Warning: (ae-missing-release-tag) "KubernetesClustersSupplier" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index feb6a4defd..fe8a52c866 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.4.7", + "version": "0.4.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -23,20 +26,20 @@ ], "configSchema": "schema.d.ts", "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-kubernetes-common": "^0.2.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-kubernetes-common": "^0.2.3", "@google-cloud/container": "^2.2.0", "@kubernetes/client-node": "^0.16.0", "@types/express": "^4.17.6", @@ -47,7 +50,7 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", - "helmet": "^4.0.0", + "helmet": "^5.0.2", "lodash": "^4.17.21", "morgan": "^1.10.0", "stream-buffers": "^3.0.2", @@ -55,7 +58,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/aws4": "^1.5.1", "supertest": "^6.1.3", "aws-sdk-mock": "^5.2.1", diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts index 4af39d4f26..9f1353ca5c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts @@ -18,19 +18,6 @@ import { sign } from 'aws4'; import { AWSClusterDetails } from '../types/types'; import { KubernetesAuthTranslator } from './types'; -const base64 = (str: string) => - Buffer.from(str.toString(), 'binary').toString('base64'); -const prepend = (prep: string) => (str: string) => prep + str; -const replace = - (search: string | RegExp, substitution: string) => (str: string) => - str.replace(search, substitution); -const pipe = - (fns: ReadonlyArray) => - (thing: string): string => - fns.reduce((val, fn) => fn(val), thing); -const removePadding = replace(/=+$/, ''); -const makeUrlSafe = pipe([replace('+', '-'), replace('/', '_')]); - type SigningCreds = { accessKeyId: string | undefined; secretAccessKey: string | undefined; @@ -117,15 +104,15 @@ export class AwsIamKubernetesAuthTranslator signQuery: true, }; - const signedRequest = sign(request, credentials); + const signed = sign(request, credentials); + const url = `https://${signed.host}${signed.path}`; + const base64Url = Buffer.from(url, 'binary').toString('base64'); + const urlSafeBase64Url = base64Url + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); - return pipe([ - (signed: any) => `https://${signed.host}${signed.path}`, - base64, - removePadding, - makeUrlSafe, - prepend('k8s-aws-v1.'), - ])(signedRequest); + return `k8s-aws-v1.${urlSafeBase64Url}`; } async decorateClusterDetailsWithAuth( diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 3333f7a0fc..a1eb60a239 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -43,6 +43,21 @@ export interface KubernetesEnvironment { config: Config; } +/** + * The return type of the `KubernetesBuilder.build` method + * + * @public + */ +export type KubernetesBuilderReturn = Promise<{ + router: express.Router; + clusterDetails: ClusterDetails[]; + clusterSupplier: KubernetesClustersSupplier; + customResources: CustomResource[]; + fetcher: KubernetesFetcher; + objectsProvider: KubernetesObjectsProvider; + serviceLocator: KubernetesServiceLocator; +}>; + export class KubernetesBuilder { private clusterSupplier?: KubernetesClustersSupplier; private objectsProvider?: KubernetesObjectsProvider; @@ -55,11 +70,23 @@ export class KubernetesBuilder { constructor(protected readonly env: KubernetesEnvironment) {} - public async build() { + public async build(): KubernetesBuilderReturn { const logger = this.env.logger; + const config = this.env.config; logger.info('Initializing Kubernetes backend'); + if (!config.has('kubernetes')) { + if (process.env.NODE_ENV !== 'development') { + throw new Error('Kubernetes configuration is missing'); + } + logger.warn( + 'Failed to initialize kubernetes backend: kubernetes config is missing', + ); + return { + router: Router(), + } as unknown as KubernetesBuilderReturn; + } const customResources = this.buildCustomResources(); const fetcher = this.fetcher ?? this.buildFetcher(); diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 785a5c619d..540e460615 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-kubernetes-common +## 0.2.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/catalog-model@0.10.1 + +## 0.2.3 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/catalog-model@0.10.0 + ## 0.2.2 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index cd12eb3519..108a9205e2 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -24,22 +27,22 @@ "dist" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test --passWithNoTests", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "bugs": { "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", + "@backstage/catalog-model": "^0.10.0", "@kubernetes/client-node": "^0.16.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 33abbb9255..75b66c0ca9 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes +## 0.5.8 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + - @backstage/plugin-kubernetes-common@0.2.3 + ## 0.5.7 ### Patch Changes diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 8dc0114738..f635a61cef 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -25,9 +25,7 @@ export const clusterLinksFormatters: Record; // Warning: (ae-missing-release-tag) "EntityKubernetesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityKubernetesContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityKubernetesContent: (_props: {}) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "FormatClusterLinkOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "formatClusterLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 1a60997405..7c5ced9480 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.5.7", + "version": "0.5.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,24 +24,24 @@ "kubernetes" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-kubernetes-common": "^0.2.2", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-kubernetes-common": "^0.2.3", "@kubernetes/client-node": "^0.16.0", - "@backstage/theme": "^0.2.14", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,10 +56,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/kubernetes/src/Router.tsx b/plugins/kubernetes/src/Router.tsx index 873bf128e4..deb6475ad5 100644 --- a/plugins/kubernetes/src/Router.tsx +++ b/plugins/kubernetes/src/Router.tsx @@ -32,10 +32,7 @@ export const isKubernetesAvailable = (entity: Entity) => entity.metadata.annotations?.[KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION], ); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const Router = (_props: Props) => { const { entity } = useEntity(); diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 541861b519..a21459ac31 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-lighthouse +## 0.2.38 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.2.37 ### Patch Changes diff --git a/plugins/lighthouse/api-report.md b/plugins/lighthouse/api-report.md index 724f8898a6..26db053ef0 100644 --- a/plugins/lighthouse/api-report.md +++ b/plugins/lighthouse/api-report.md @@ -70,9 +70,7 @@ export const EntityLastLighthouseAuditCard: ({ // Warning: (ae-missing-release-tag) "EntityLighthouseContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityLighthouseContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityLighthouseContent: (_props: {}) => JSX.Element; // Warning: (ae-missing-release-tag) "FetchError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 618202b54c..ff58fb7ed2 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.2.37", + "version": "0.2.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,22 +25,22 @@ "lighthouse" ], "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "clean": "backstage-cli clean", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "start": "backstage-cli plugin:serve" + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/lighthouse/src/Router.tsx b/plugins/lighthouse/src/Router.tsx index 917001c591..1c41f522f4 100644 --- a/plugins/lighthouse/src/Router.tsx +++ b/plugins/lighthouse/src/Router.tsx @@ -36,10 +36,7 @@ export const Router = () => ( ); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const EmbeddedRouter = (_props: Props) => { const { entity } = useEntity(); diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index e1101d2369..f47372401c 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-newrelic-dashboard +## 0.1.7 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + ## 0.1.6 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index dba9cc1148..04714bc389 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,30 +9,33 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/dev-utils": "^0.2.21", + "@backstage/cli": "^0.14.0", + "@backstage/dev-utils": "^0.2.22", "@testing-library/jest-dom": "^5.10.1", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5" diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 821de4582a..ce38f0bd86 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic +## 0.3.17 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.3.16 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 9f9d51eae3..6e5e5c8291 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.16", + "version": "0.3.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,19 +25,19 @@ "newrelic" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -44,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 76b3945a5d..d80405bf2e 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-org +## 0.4.3 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + +## 0.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.8.8 + - @backstage/plugin-catalog-react@0.6.14 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/org/api-report.md b/plugins/org/api-report.md index b181a3aab4..723cbd43b7 100644 --- a/plugins/org/api-report.md +++ b/plugins/org/api-report.md @@ -6,11 +6,8 @@ /// import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; -import { GroupEntity } from '@backstage/catalog-model'; import { InfoCardVariants } from '@backstage/core-components'; -import { UserEntity } from '@backstage/catalog-model'; // Warning: (ae-missing-release-tag) "EntityGroupProfileCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -18,7 +15,6 @@ import { UserEntity } from '@backstage/catalog-model'; export const EntityGroupProfileCard: ({ variant, }: { - entity?: GroupEntity | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; @@ -26,7 +22,6 @@ export const EntityGroupProfileCard: ({ // // @public (undocumented) export const EntityMembersListCard: (_props: { - entity?: GroupEntity | undefined; memberDisplayTitle?: string | undefined; pageSize?: number | undefined; }) => JSX.Element; @@ -38,7 +33,6 @@ export const EntityOwnershipCard: ({ variant, entityFilterKind, }: { - entity?: Entity | undefined; variant?: InfoCardVariants | undefined; entityFilterKind?: string[] | undefined; }) => JSX.Element; @@ -49,7 +43,6 @@ export const EntityOwnershipCard: ({ export const EntityUserProfileCard: ({ variant, }: { - entity?: UserEntity | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; @@ -59,7 +52,6 @@ export const EntityUserProfileCard: ({ export const GroupProfileCard: ({ variant, }: { - entity?: GroupEntity | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; @@ -67,7 +59,6 @@ export const GroupProfileCard: ({ // // @public (undocumented) export const MembersListCard: (_props: { - entity?: GroupEntity; memberDisplayTitle?: string; pageSize?: number; }) => JSX.Element; @@ -91,7 +82,6 @@ export const OwnershipCard: ({ variant, entityFilterKind, }: { - entity?: Entity | undefined; variant?: InfoCardVariants | undefined; entityFilterKind?: string[] | undefined; }) => JSX.Element; @@ -102,7 +92,6 @@ export const OwnershipCard: ({ export const UserProfileCard: ({ variant, }: { - entity?: UserEntity | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; ``` diff --git a/plugins/org/package.json b/plugins/org/package.json index 58f293fa8c..b95d283c20 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.4.2-next.0", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,22 +10,25 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,11 +42,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/catalog-client": "^0.7.0", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx index b44fbe6c5c..8d5a553860 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx @@ -58,8 +58,6 @@ const CardTitle = ({ title }: { title: string }) => ( export const GroupProfileCard = ({ variant, }: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: GroupEntity; variant?: InfoCardVariants; }) => { const { entity: group } = useEntity(); diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 9a107f2d8f..67bf5c2e42 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, GroupEntity, UserEntity, stringifyEntityRef, @@ -109,8 +109,6 @@ const MemberComponent = ({ member }: { member: UserEntity }) => { }; export const MembersListCard = (_props: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: GroupEntity; memberDisplayTitle?: string; pageSize?: number; }) => { @@ -124,7 +122,7 @@ export const MembersListCard = (_props: { const displayName = profile?.displayName ?? groupName; - const groupNamespace = grpNamespace || ENTITY_DEFAULT_NAMESPACE; + const groupNamespace = grpNamespace || DEFAULT_NAMESPACE; const [page, setPage] = React.useState(1); const pageChange = (_: React.ChangeEvent, pageIndex: number) => { diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx index 26a79dfaee..2030f4c100 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx @@ -15,8 +15,8 @@ */ import { - CatalogEntitiesRequest, - CatalogListResponse, + GetEntitiesRequest, + GetEntitiesResponse, } from '@backstage/catalog-client'; import { Entity, GroupEntity, UserEntity } from '@backstage/catalog-model'; import { @@ -110,15 +110,15 @@ const items = [ ] as Entity[]; const getEntitiesMock = ( - request?: CatalogEntitiesRequest, -): Promise> => { + request?: GetEntitiesRequest, +): Promise => { const filterKinds = !Array.isArray(request?.filter) && Array.isArray(request?.filter?.kind) ? request?.filter?.kind ?? [] : []; // we expect the request to be like { filter: { kind: ['API','System'], .... }. If changed in OwnerShipCard, let's change in also here return Promise.resolve({ items: items.filter(item => filterKinds.find(k => k === item.kind)), - } as CatalogListResponse); + } as GetEntitiesResponse); }; describe('OwnershipCard', () => { diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx index c89534ea7a..2b292cbe8b 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx +++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx @@ -131,8 +131,6 @@ export const OwnershipCard = ({ variant, entityFilterKind, }: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; variant?: InfoCardVariants; entityFilterKind?: string[]; }) => { diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx index 7b9904954f..cf84381830 100644 --- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx +++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.test.tsx @@ -55,7 +55,7 @@ describe('UserSummary Test', () => { const rendered = await renderWithEffects( wrapInTestApp( - + , { mountedRoutes: { diff --git a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx index 0997e0a4d8..bafaad7ba0 100644 --- a/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx +++ b/plugins/org/src/components/Cards/User/UserProfileCard/UserProfileCard.tsx @@ -51,8 +51,6 @@ const CardTitle = ({ title }: { title?: string }) => export const UserProfileCard = ({ variant, }: { - /** @deprecated The entity is now grabbed from context instead */ - entity?: UserEntity; variant?: InfoCardVariants; }) => { const { entity: user } = useEntity(); diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 6fbcfc54b1..5d19df1299 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-pagerduty +## 0.3.26 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- edeeac7e9d: Switch `luxon` dependency range to be `^2.0.2` rather than `2.0.2`. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.3.25 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 7912a32f15..11a007907a 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.3.25", + "version": "0.3.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,26 +24,26 @@ "pagerduty" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "classnames": "^2.2.6", - "luxon": "2.0.2", + "luxon": "^2.0.2", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4" }, @@ -49,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx index ef0659becb..171238cdd3 100644 --- a/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx +++ b/plugins/pagerduty/src/components/TriggerDialog/TriggerDialog.tsx @@ -34,10 +34,7 @@ import { alertApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { - ENTITY_DEFAULT_NAMESPACE, - parseEntityRef, -} from '@backstage/catalog-model'; +import { DEFAULT_NAMESPACE, parseEntityRef } from '@backstage/catalog-model'; type Props = { showDialog: boolean; @@ -61,7 +58,7 @@ export const TriggerDialog = ({ const { userEntityRef } = await identityApi.getBackstageIdentity(); const { name: userName } = parseEntityRef(userEntityRef, { defaultKind: 'User', - defaultNamespace: ENTITY_DEFAULT_NAMESPACE, + defaultNamespace: DEFAULT_NAMESPACE, }); await api.triggerAlarm({ integrationKey: integrationKey as string, diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 58ace0ff17..5ac4977129 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-permission-backend +## 0.5.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/plugin-auth-node@0.1.2 + - @backstage/plugin-permission-common@0.5.1 + - @backstage/plugin-permission-node@0.5.1 + +## 0.5.0 + +### Minor Changes + +- e2cf0662eb: Add a warning if the permission backend is used without setting `permission.enabled=true`. + + **BREAKING** Permission backend's `createRouter` now requires a `config` option. + + ```diff + // packages/backend/src/plugins/permission.ts + + ... + export default async function createPlugin({ + ... + + config, + }: PluginEnvironment) { + return createRouter({ + ... + + config, + }); + } + ``` + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/plugin-auth-node@0.1.1 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/config@0.1.14 + - @backstage/plugin-permission-node@0.5.0 + ## 0.4.3 ### Patch Changes diff --git a/plugins/permission-backend/api-report.md b/plugins/permission-backend/api-report.md index 843c9a315c..2b59113535 100644 --- a/plugins/permission-backend/api-report.md +++ b/plugins/permission-backend/api-report.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { Config } from '@backstage/config'; import express from 'express'; import { IdentityClient } from '@backstage/plugin-auth-node'; import { Logger as Logger_2 } from 'winston'; @@ -14,6 +15,8 @@ export function createRouter(options: RouterOptions): Promise; // @public export interface RouterOptions { + // (undocumented) + config: Config; // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index e1a4e10c5c..d66637f76c 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.4.3", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,22 +9,25 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-auth-node": "^0.1.0", - "@backstage/plugin-permission-common": "^0.4.0", - "@backstage/plugin-permission-node": "^0.4.3", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-auth-node": "^0.1.1", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-node": "^0.5.0", "@types/express": "*", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -36,7 +39,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "supertest": "^6.1.6", diff --git a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts index 4be1b55379..9981496658 100644 --- a/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts +++ b/plugins/permission-backend/src/service/PermissionIntegrationClient.test.ts @@ -20,7 +20,11 @@ import express, { Router, RequestHandler } from 'express'; import { RestContext, rest } from 'msw'; import { setupServer, SetupServerApi } from 'msw/node'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + AuthorizeResult, + PermissionCondition, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node'; import { PermissionIntegrationClient } from './PermissionIntegrationClient'; @@ -28,7 +32,7 @@ describe('PermissionIntegrationClient', () => { describe('applyConditions', () => { let server: SetupServerApi; - const mockConditions = { + const mockConditions: PermissionCriteria = { not: { allOf: [ { rule: 'RULE_1', params: [] }, diff --git a/plugins/permission-backend/src/service/router.test.ts b/plugins/permission-backend/src/service/router.test.ts index 498fcb748b..b98b32b01c 100644 --- a/plugins/permission-backend/src/service/router.test.ts +++ b/plugins/permission-backend/src/service/router.test.ts @@ -26,6 +26,7 @@ import { import { PermissionIntegrationClient } from './PermissionIntegrationClient'; import { createRouter } from './router'; +import { ConfigReader } from '@backstage/config'; const mockApplyConditions: jest.MockedFunction< InstanceType['applyConditions'] @@ -63,6 +64,7 @@ describe('createRouter', () => { beforeAll(async () => { const router = await createRouter({ + config: new ConfigReader({ permission: { enabled: true } }), logger: getVoidLogger(), discovery: { getBaseUrl: jest.fn(), diff --git a/plugins/permission-backend/src/service/router.ts b/plugins/permission-backend/src/service/router.ts index 413f3e6b45..48f7b1a2e5 100644 --- a/plugins/permission-backend/src/service/router.ts +++ b/plugins/permission-backend/src/service/router.ts @@ -44,6 +44,7 @@ import { import { PermissionIntegrationClient } from './PermissionIntegrationClient'; import { memoize } from 'lodash'; import DataLoader from 'dataloader'; +import { Config } from '@backstage/config'; const querySchema: z.ZodSchema> = z.object({ id: z.string(), @@ -79,6 +80,7 @@ export interface RouterOptions { discovery: PluginEndpointDiscovery; policy: PermissionPolicy; identity: IdentityClient; + config: Config; } const handleRequest = async ( @@ -139,7 +141,13 @@ const handleRequest = async ( export async function createRouter( options: RouterOptions, ): Promise { - const { policy, discovery, identity } = options; + const { policy, discovery, identity, config, logger } = options; + + if (!config.getOptionalBoolean('permission.enabled')) { + logger.warn( + 'Permission backend started with permissions disabled. Enable permissions by setting permission.enabled=true.', + ); + } const permissionIntegrationClient = new PermissionIntegrationClient({ discovery, diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index c0c21288be..b7162ecb06 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-permission-common +## 0.5.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + +## 0.5.0 + +### Minor Changes + +- 8c646beb24: **BREAKING** `PermissionCriteria` now requires at least one condition in `anyOf` and `allOf` arrays. This addresses some ambiguous behavior outlined in #9280. + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + ## 0.4.0 ### Minor Changes diff --git a/plugins/permission-common/api-report.md b/plugins/permission-common/api-report.md index 30a67e8c8b..db05766dc0 100644 --- a/plugins/permission-common/api-report.md +++ b/plugins/permission-common/api-report.md @@ -5,6 +5,16 @@ ```ts import { Config } from '@backstage/config'; +// @public +export type AllOfCriteria = { + allOf: NonEmptyArray>; +}; + +// @public +export type AnyOfCriteria = { + anyOf: NonEmptyArray>; +}; + // @public export type AuthorizeDecision = | { @@ -65,6 +75,11 @@ export function isReadPermission(permission: Permission): boolean; // @public export function isUpdatePermission(permission: Permission): boolean; +// @public +export type NotCriteria = { + not: PermissionCriteria; +}; + // @public export type Permission = { name: string; @@ -103,14 +118,8 @@ export type PermissionCondition = { // @public export type PermissionCriteria = - | { - allOf: PermissionCriteria[]; - } - | { - anyOf: PermissionCriteria[]; - } - | { - not: PermissionCriteria; - } + | AllOfCriteria + | AnyOfCriteria + | NotCriteria | TQuery; ``` diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index d3054fe9fe..4961b583a2 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -10,6 +10,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -27,25 +30,25 @@ ], "configSchema": "config.d.ts", "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "bugs": { "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", "cross-fetch": "^3.1.5", "uuid": "^8.0.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "msw": "^0.35.0" } diff --git a/plugins/permission-common/src/PermissionClient.ts b/plugins/permission-common/src/PermissionClient.ts index 58f4d44d20..9431050690 100644 --- a/plugins/permission-common/src/PermissionClient.ts +++ b/plugins/permission-common/src/PermissionClient.ts @@ -43,9 +43,18 @@ const permissionCriteriaSchema: z.ZodSchema< rule: z.string(), params: z.array(z.unknown()), }) - .or(z.object({ anyOf: z.array(permissionCriteriaSchema) })) - .or(z.object({ allOf: z.array(permissionCriteriaSchema) })) - .or(z.object({ not: permissionCriteriaSchema })), + .strict() + .or( + z + .object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }) + .strict(), + ) + .or( + z + .object({ allOf: z.array(permissionCriteriaSchema).nonempty() }) + .strict(), + ) + .or(z.object({ not: permissionCriteriaSchema }).strict()), ); const responseSchema = z.object({ diff --git a/plugins/permission-common/src/types/api.ts b/plugins/permission-common/src/types/api.ts index 287c7ffe83..e0ab1f1642 100644 --- a/plugins/permission-common/src/types/api.ts +++ b/plugins/permission-common/src/types/api.ts @@ -72,14 +72,44 @@ export type PermissionCondition = { params: TParams; }; +/** + * Utility type to represent an array with 1 or more elements. + * @ignore + */ +type NonEmptyArray = [T, ...T[]]; + +/** + * Represnts a logical AND for the provided criteria. + * @public + */ +export type AllOfCriteria = { + allOf: NonEmptyArray>; +}; + +/** + * Represnts a logical OR for the provided criteria. + * @public + */ +export type AnyOfCriteria = { + anyOf: NonEmptyArray>; +}; + +/** + * Represents a negation of the provided criteria. + * @public + */ +export type NotCriteria = { + not: PermissionCriteria; +}; + /** * Composes several {@link PermissionCondition}s as criteria with a nested AND/OR structure. * @public */ export type PermissionCriteria = - | { allOf: PermissionCriteria[] } - | { anyOf: PermissionCriteria[] } - | { not: PermissionCriteria } + | AllOfCriteria + | AnyOfCriteria + | NotCriteria | TQuery; /** diff --git a/plugins/permission-common/src/types/index.ts b/plugins/permission-common/src/types/index.ts index b4453fcc63..fa98de73f1 100644 --- a/plugins/permission-common/src/types/index.ts +++ b/plugins/permission-common/src/types/index.ts @@ -23,6 +23,9 @@ export type { Identified, PermissionCondition, PermissionCriteria, + AllOfCriteria, + AnyOfCriteria, + NotCriteria, } from './api'; export type { DiscoveryApi } from './discovery'; export type { diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index d79c79159f..44827b4f20 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-permission-node +## 0.5.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/plugin-auth-node@0.1.2 + - @backstage/plugin-permission-common@0.5.1 + +## 0.5.0 + +### Minor Changes + +- 8c646beb24: **BREAKING** `PermissionCriteria` now requires at least one condition in `anyOf` and `allOf` arrays. This addresses some ambiguous behavior outlined in #9280. + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/plugin-auth-node@0.1.1 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/config@0.1.14 + ## 0.4.3 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 04a567f16b..2157c9e0dd 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.4.3", + "version": "0.5.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,26 +24,27 @@ "permissions" ], "scripts": { - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-auth-node": "^0.1.0", - "@backstage/plugin-permission-common": "^0.4.0", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-auth-node": "^0.1.1", + "@backstage/plugin-permission-common": "^0.5.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/permission-node/src/integration/createConditionTransformer.ts b/plugins/permission-node/src/integration/createConditionTransformer.ts index 0e736b832c..ee4224b8bd 100644 --- a/plugins/permission-node/src/integration/createConditionTransformer.ts +++ b/plugins/permission-node/src/integration/createConditionTransformer.ts @@ -14,6 +14,8 @@ * limitations under the License. */ import { + AllOfCriteria, + AnyOfCriteria, PermissionCondition, PermissionCriteria, } from '@backstage/plugin-permission-common'; @@ -32,11 +34,11 @@ const mapConditions = ( if (isAndCriteria(criteria)) { return { allOf: criteria.allOf.map(child => mapConditions(child, getRule)), - }; + } as AllOfCriteria; } else if (isOrCriteria(criteria)) { return { anyOf: criteria.anyOf.map(child => mapConditions(child, getRule)), - }; + } as AnyOfCriteria; } else if (isNotCriteria(criteria)) { return { not: mapConditions(criteria.not, getRule), diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts index 065c30a978..6408de46a1 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.test.ts @@ -247,7 +247,8 @@ describe('createPermissionIntegrationRouter', () => { resourceRef: 'default:test/resource-1', resourceType: 'test-incorrect-resource-1', conditions: { - anyOf: [], + rule: 'test-rule-1', + params: [{}], }, }, { @@ -255,7 +256,8 @@ describe('createPermissionIntegrationRouter', () => { resourceRef: 'default:test/resource-2', resourceType: 'test-resource', conditions: { - anyOf: [], + rule: 'test-rule-1', + params: [{}], }, }, { @@ -263,7 +265,8 @@ describe('createPermissionIntegrationRouter', () => { resourceRef: 'default:test/resource-3', resourceType: 'test-incorrect-resource-2', conditions: { - anyOf: [], + rule: 'test-rule-1', + params: [{}], }, }, ], diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts index 1b01660fb0..efb5d7c3a6 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts @@ -38,13 +38,15 @@ const permissionCriteriaSchema: z.ZodSchema< PermissionCriteria > = z.lazy(() => z.union([ - z.object({ anyOf: z.array(permissionCriteriaSchema) }), - z.object({ allOf: z.array(permissionCriteriaSchema) }), - z.object({ not: permissionCriteriaSchema }), - z.object({ - rule: z.string(), - params: z.array(z.unknown()), - }), + z.object({ anyOf: z.array(permissionCriteriaSchema).nonempty() }).strict(), + z.object({ allOf: z.array(permissionCriteriaSchema).nonempty() }).strict(), + z.object({ not: permissionCriteriaSchema }).strict(), + z + .object({ + rule: z.string(), + params: z.array(z.unknown()), + }) + .strict(), ]), ); diff --git a/plugins/permission-node/src/integration/util.ts b/plugins/permission-node/src/integration/util.ts index d9457cfefc..3878e18895 100644 --- a/plugins/permission-node/src/integration/util.ts +++ b/plugins/permission-node/src/integration/util.ts @@ -14,22 +14,27 @@ * limitations under the License. */ -import { PermissionCriteria } from '@backstage/plugin-permission-common'; +import { + AllOfCriteria, + AnyOfCriteria, + NotCriteria, + PermissionCriteria, +} from '@backstage/plugin-permission-common'; import { PermissionRule } from '../types'; export const isAndCriteria = ( filter: PermissionCriteria, -): filter is { allOf: PermissionCriteria[] } => +): filter is AllOfCriteria => Object.prototype.hasOwnProperty.call(filter, 'allOf'); export const isOrCriteria = ( filter: PermissionCriteria, -): filter is { anyOf: PermissionCriteria[] } => +): filter is AnyOfCriteria => Object.prototype.hasOwnProperty.call(filter, 'anyOf'); export const isNotCriteria = ( filter: PermissionCriteria, -): filter is { not: PermissionCriteria } => +): filter is NotCriteria => Object.prototype.hasOwnProperty.call(filter, 'not'); export const createGetRule = ( diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index 41c55b5a45..db0b1a3a1f 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-react +## 0.3.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/config@0.1.14 + ## 0.3.0 ### Minor Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index ce6e2dbf54..2fc639f432 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.3.0", + "version": "0.3.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,6 +9,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "web-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -19,17 +22,18 @@ "backstage" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-permission-common": "^0.4.0", + "@backstage/config": "^0.1.14", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-permission-common": "^0.5.0", "cross-fetch": "^3.1.5", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4", @@ -40,8 +44,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0", - "@backstage/test-utils": "^0.2.4-next.0", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@types/jest": "^26.0.7" diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 7460eddd5a..de7aa6dc0a 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-proxy-backend +## 0.2.20 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + +## 0.2.19 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 + ## 0.2.18 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 5336bbb098..b0635be7f9 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.18", + "version": "0.2.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -20,17 +23,17 @@ "backstage" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -43,7 +46,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 14e566219a..06431bd21b 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-rollbar-backend +## 0.1.23 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + +## 0.1.22 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 1433045c08: Removed unused `helmet` dependency. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 + ## 0.1.21 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 36683ef66a..141b35d373 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.21", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,17 +25,17 @@ "rollbar" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", "@types/express": "^4.17.6", "camelcase-keys": "^7.0.1", "compression": "^1.7.4", @@ -40,7 +43,6 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "fs-extra": "9.1.0", - "helmet": "^4.0.0", "lodash": "^4.17.21", "morgan": "^1.10.0", "node-fetch": "^2.6.7", @@ -48,8 +50,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/supertest": "^2.0.8", "msw": "^0.36.3", "supertest": "^6.1.3" diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index df1cb19f83..5e1b3fc9ed 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-rollbar +## 0.3.27 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.3.26 ### Patch Changes diff --git a/plugins/rollbar/api-report.md b/plugins/rollbar/api-report.md index fbdbd36208..f666ade34c 100644 --- a/plugins/rollbar/api-report.md +++ b/plugins/rollbar/api-report.md @@ -12,18 +12,15 @@ import { Entity } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; import { RouteRef } from '@backstage/core-plugin-api'; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "EntityPageRollbar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityPageRollbar: (_props: Props) => JSX.Element; +export const EntityPageRollbar: () => JSX.Element; // Warning: (ae-missing-release-tag) "EntityRollbarContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityRollbarContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityRollbarContent: (_props: {}) => JSX.Element; // Warning: (ae-missing-release-tag) "isPluginApplicableToEntity" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -103,5 +100,5 @@ export { rollbarPlugin }; // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: (_props: Props_2) => JSX.Element; +export const Router: (_props: Props) => JSX.Element; ``` diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 5767f26c5e..06277a3d5f 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.3.26", + "version": "0.3.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,21 +25,21 @@ "rollbar" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/rollbar/src/components/EntityPageRollbar/EntityPageRollbar.tsx b/plugins/rollbar/src/components/EntityPageRollbar/EntityPageRollbar.tsx index 8b51691778..626b3442e5 100644 --- a/plugins/rollbar/src/components/EntityPageRollbar/EntityPageRollbar.tsx +++ b/plugins/rollbar/src/components/EntityPageRollbar/EntityPageRollbar.tsx @@ -14,17 +14,11 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import React from 'react'; import { RollbarProject } from '../RollbarProject/RollbarProject'; -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; - -export const EntityPageRollbar = (_props: Props) => { +export const EntityPageRollbar = () => { const { entity } = useEntity(); return ; diff --git a/plugins/rollbar/src/components/Router.tsx b/plugins/rollbar/src/components/Router.tsx index 032bf0166e..a11acb379c 100644 --- a/plugins/rollbar/src/components/Router.tsx +++ b/plugins/rollbar/src/components/Router.tsx @@ -25,10 +25,7 @@ import { MissingAnnotationEmptyState } from '@backstage/core-components'; export const isPluginApplicableToEntity = (entity: Entity) => Boolean(entity.metadata.annotations?.[ROLLBAR_ANNOTATION]); -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const Router = (_props: Props) => { const { entity } = useEntity(); @@ -39,7 +36,7 @@ export const Router = (_props: Props) => { return ( - } /> + } /> ); }; diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 29ff4e9edb..a5d2aa1b3f 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/types@0.1.3 + - @backstage/plugin-scaffolder-backend@0.16.1 + +## 0.2.0 + +### Minor Changes + +- 661594bf43: Updated to the latest version of `@backstage/plugin-scaffolder-backend`, meaning the `TemplateAction` now exposes the precise input type rather than `any`. + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/plugin-scaffolder-backend@0.16.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.1.11 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/api-report.md b/plugins/scaffolder-backend-module-cookiecutter/api-report.md index 132d3d4225..e55c6368c4 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/api-report.md +++ b/plugins/scaffolder-backend-module-cookiecutter/api-report.md @@ -6,6 +6,7 @@ /// import { ContainerRunner } from '@backstage/backend-common'; +import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-backend'; import { UrlReader } from '@backstage/backend-common'; @@ -15,5 +16,12 @@ export function createFetchCookiecutterAction(options: { reader: UrlReader; integrations: ScmIntegrations; containerRunner: ContainerRunner; -}): TemplateAction; +}): TemplateAction<{ + url: string; + targetPath?: string | undefined; + values: JsonObject; + copyWithoutRender?: string[] | undefined; + extensions?: string[] | undefined; + imageName?: string | undefined; +}>; ``` diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index cee138b576..e56f67d43a 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.1.11", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,29 +10,32 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-scaffolder-backend": "^0.15.24", - "@backstage/config": "^0.1.13", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-scaffolder-backend": "^0.16.0", + "@backstage/config": "^0.1.14", + "@backstage/types": "^0.1.2", "command-exists": "^1.2.9", "fs-extra": "10.0.0", "winston": "^3.2.1", "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts index bba51e3f01..2c1ecd06f9 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.test.ts @@ -89,7 +89,10 @@ describe('fetch:cookiecutter', () => { help: 'me', }, }, - baseUrl: 'somebase', + templateInfo: { + entityRef: 'template:default/cookiecutter', + baseUrl: 'somebase', + }, workspacePath: mockTmpDir, logger: getVoidLogger(), logStream: new PassThrough(), @@ -149,7 +152,7 @@ describe('fetch:cookiecutter', () => { expect.objectContaining({ reader: mockReader, integrations, - baseUrl: mockContext.baseUrl, + baseUrl: mockContext.templateInfo?.baseUrl, fetchUrl: mockContext.input.url, outputPath: join( mockTmpDir, diff --git a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts index c4d7f1e3e8..0455f01989 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend-module-cookiecutter/src/actions/fetch/cookiecutter.ts @@ -222,7 +222,7 @@ export function createFetchCookiecutterAction(options: { await fetchContents({ reader, integrations, - baseUrl: ctx.baseUrl, + baseUrl: ctx.templateInfo?.baseUrl, fetchUrl: ctx.input.url, outputPath: templateContentsDir, }); diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 2b369835f8..9ae5d7f592 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.3.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/types@0.1.3 + - @backstage/plugin-scaffolder-backend@0.16.1 + +## 0.3.0 + +### Minor Changes + +- 661594bf43: Updated to the latest version of `@backstage/plugin-scaffolder-backend`, meaning the `TemplateAction` now exposes the precise input type rather than `any`. + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/plugin-scaffolder-backend@0.16.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.2.6 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/api-report.md b/plugins/scaffolder-backend-module-rails/api-report.md index 9c0610d4f2..aa631c5333 100644 --- a/plugins/scaffolder-backend-module-rails/api-report.md +++ b/plugins/scaffolder-backend-module-rails/api-report.md @@ -4,6 +4,7 @@ ```ts import { ContainerRunner } from '@backstage/backend-common'; +import { JsonObject } from '@backstage/types'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-backend'; import { UrlReader } from '@backstage/backend-common'; @@ -13,5 +14,10 @@ export function createFetchRailsAction(options: { reader: UrlReader; integrations: ScmIntegrations; containerRunner: ContainerRunner; -}): TemplateAction; +}): TemplateAction<{ + url: string; + targetPath?: string | undefined; + values: JsonObject; + imageName?: string | undefined; +}>; ``` diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 5f32dbadd8..b4c093792d 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.2.6", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,27 +11,30 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "scripts": { - "build": "backstage-cli backend:build", - "start": "backstage-cli backend:dev", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/plugin-scaffolder-backend": "^0.15.24", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/plugin-scaffolder-backend": "^0.16.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/types": "^0.1.2", "command-exists": "^1.2.9", "fs-extra": "^9.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index 0c7552f72f..0a6a996aa8 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -62,7 +62,10 @@ describe('fetch:rails', () => { help: 'me', }, }, - baseUrl: 'somebase', + templateInfo: { + baseUrl: 'somebase', + entityRef: 'template:default/myTemplate', + }, workspacePath: mockTmpDir, logger: getVoidLogger(), logStream: new PassThrough(), @@ -100,7 +103,7 @@ describe('fetch:rails', () => { expect(fetchContents).toHaveBeenCalledWith({ reader: mockReader, integrations, - baseUrl: mockContext.baseUrl, + baseUrl: mockContext.templateInfo.baseUrl, fetchUrl: mockContext.input.url, outputPath: resolvePath(mockContext.workspacePath), }); diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts index 2865361a8b..132929ee1c 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts @@ -170,7 +170,7 @@ export function createFetchRailsAction(options: { await fetchContents({ reader, integrations, - baseUrl: ctx.baseUrl, + baseUrl: ctx.templateInfo?.baseUrl, fetchUrl: ctx.input.url, outputPath: workDir, }); diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 8c5a6ade44..815bffc400 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.0 + +### Minor Changes + +- 661594bf43: Updated to the latest version of `@backstage/plugin-scaffolder-backend`, meaning the `TemplateAction` now exposes the precise input type rather than `any`. + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- c82cd1b137: Bump `yeoman-environment` dependency from `^3.6.0` to `^3.9.1`. +- Updated dependencies + - @backstage/plugin-scaffolder-backend@0.16.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + ## 0.1.5 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/api-report.md b/plugins/scaffolder-backend-module-yeoman/api-report.md index fc18814faa..0f8747e592 100644 --- a/plugins/scaffolder-backend-module-yeoman/api-report.md +++ b/plugins/scaffolder-backend-module-yeoman/api-report.md @@ -3,8 +3,13 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { JsonObject } from '@backstage/types'; import { TemplateAction } from '@backstage/plugin-scaffolder-backend'; // @public -export function createRunYeomanAction(): TemplateAction; +export function createRunYeomanAction(): TemplateAction<{ + namespace: string; + args?: string[] | undefined; + options?: JsonObject | undefined; +}>; ``` diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index a49898be1c..df42d18ac7 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.1.5", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,24 +10,27 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/plugin-scaffolder-backend": "^0.15.24", - "@backstage/types": "^0.1.1", + "@backstage/config": "^0.1.14", + "@backstage/plugin-scaffolder-backend": "^0.16.0", + "@backstage/types": "^0.1.2", "winston": "^3.2.1", - "yeoman-environment": "^3.6.0" + "yeoman-environment": "^3.9.1" }, "devDependencies": { - "@backstage/backend-common": "^0.10.7", + "@backstage/backend-common": "^0.10.8", "@types/jest": "^26.0.7" }, "files": [ diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 7c80464d71..eaa1261146 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-scaffolder-backend +## 0.16.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/types@0.1.3 + - @backstage/plugin-catalog-backend@0.21.5 + - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.1 + - @backstage/plugin-scaffolder-common@0.2.1 + +## 0.16.0 + +### Minor Changes + +- 661594bf43: **BREAKING**: Updated `TemplateAction` and related types to have its type parameter extend `JsonObject` instead of `InputBase`. The `createTemplateAction` has also been updated to pass through the `TInput` type parameter to the return type, meaning the `TemplateAction` retains its type. This can lead to breakages during type checking especially within tests. +- 8db2b671c6: **BREAKING**: `ctx.token` is now `ctx.secrets.backstageToken` in Actions. Please update any of your Actions that might call out to Backstage API's with this token. +- 5a1594330e: **BREAKING** - Removed the `CatalogEntityClient` export. This is no longer provider by this package, + but you can implement one pretty simply yourself using the `CatalogApi` and applying filters to fetch templates. +- 7d3471db94: Remove the previously deprecated `scaffolder.provider` config for all providers. + This config is no longer used anywhere, and adopters should use [`integrations` config](https://backstage.io/docs/integrations) instead. + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- 3e59f90b51: Fix error handling of the `runCommand` helper to return `Error` + instance. +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead + of `@backstage/catalog-model`. +- 1433045c08: Removed unused `helmet` dependency. +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/plugin-scaffolder-common@0.2.0 + - @backstage/plugin-catalog-backend@0.21.4 + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/types@0.1.2 + - @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.0 + ## 0.15.24 ### Patch Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 5e7b5a428b..c0ff3b3f2b 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -29,43 +29,29 @@ import { SpawnOptionsWithoutStdio } from 'child_process'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta2 } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; import { TemplateMetadata } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; -// Warning: (ae-forgotten-export) The symbol "InputBase" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ActionContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type ActionContext = { +export type ActionContext = { baseUrl?: string; logger: Logger_2; logStream: Writable; - token?: string | undefined; secrets?: TaskSecrets; workspacePath: string; input: Input; output(name: string, value: JsonValue): void; createTemporaryDirectory(): Promise; metadata?: TemplateMetadata; + templateInfo?: TemplateInfo; }; -// Warning: (ae-missing-release-tag) "CatalogEntityClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public -export class CatalogEntityClient { - constructor(catalogClient: CatalogApi); - findTemplate( - templateName: string, - options?: { - token?: string; - }, - ): Promise; -} - -// @public -export type CompletedTaskState = 'failed' | 'completed'; +// @public @deprecated +export type CompletedTaskState = TaskCompletionState; // Warning: (ae-missing-release-tag) "createBuiltinActions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -77,7 +63,7 @@ export const createBuiltinActions: (options: { containerRunner?: ContainerRunner; config: Config; additionalTemplateFilters?: Record; -}) => TemplateAction[]; +}) => TemplateAction[]; // Warning: (ae-missing-release-tag) "createCatalogRegisterAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -85,17 +71,33 @@ export const createBuiltinActions: (options: { export function createCatalogRegisterAction(options: { catalogClient: CatalogApi; integrations: ScmIntegrations; -}): TemplateAction; +}): TemplateAction< + | { + catalogInfoUrl: string; + optional?: boolean | undefined; + } + | { + repoContentsUrl: string; + catalogInfoPath?: string | undefined; + optional?: boolean | undefined; + } +>; // Warning: (ae-missing-release-tag) "createCatalogWriteAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function createCatalogWriteAction(): TemplateAction; +export function createCatalogWriteAction(): TemplateAction<{ + filePath?: string | undefined; + entity: Entity; +}>; // Warning: (ae-missing-release-tag) "createDebugLogAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export function createDebugLogAction(): TemplateAction; +export function createDebugLogAction(): TemplateAction<{ + message?: string | undefined; + listWorkspace?: boolean | undefined; +}>; export { createFetchCookiecutterAction }; @@ -105,7 +107,10 @@ export { createFetchCookiecutterAction }; export function createFetchPlainAction(options: { reader: UrlReader; integrations: ScmIntegrations; -}): TemplateAction; +}): TemplateAction<{ + url: string; + targetPath?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createFetchTemplateAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -114,17 +119,32 @@ export function createFetchTemplateAction(options: { reader: UrlReader; integrations: ScmIntegrations; additionalTemplateFilters?: Record; -}): TemplateAction; +}): TemplateAction<{ + url: string; + targetPath?: string | undefined; + values: any; + templateFileExtension?: string | boolean | undefined; + copyWithoutRender?: string[] | undefined; + cookiecutterCompat?: boolean | undefined; +}>; // Warning: (ae-missing-release-tag) "createFilesystemDeleteAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const createFilesystemDeleteAction: () => TemplateAction; +export const createFilesystemDeleteAction: () => TemplateAction<{ + files: string[]; +}>; // Warning: (ae-missing-release-tag) "createFilesystemRenameAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const createFilesystemRenameAction: () => TemplateAction; +export const createFilesystemRenameAction: () => TemplateAction<{ + files: Array<{ + from: string; + to: string; + overwrite?: boolean; + }>; +}>; // Warning: (ae-missing-release-tag) "createGithubActionsDispatchAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -132,7 +152,17 @@ export const createFilesystemRenameAction: () => TemplateAction; export function createGithubActionsDispatchAction(options: { integrations: ScmIntegrations; githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + workflowId: string; + branchOrTagName: string; + workflowInputs?: + | { + [key: string]: string; + } + | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createGithubWebhookAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -141,7 +171,16 @@ export function createGithubWebhookAction(options: { integrations: ScmIntegrationRegistry; defaultWebhookSecret?: string; githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + webhookUrl: string; + webhookSecret?: string | undefined; + events?: string[] | undefined; + active?: boolean | undefined; + contentType?: 'form' | 'json' | undefined; + insecureSsl?: boolean | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createPublishAzureAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -149,7 +188,13 @@ export function createGithubWebhookAction(options: { export function createPublishAzureAction(options: { integrations: ScmIntegrationRegistry; config: Config; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + sourcePath?: string | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createPublishBitbucketAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -157,12 +202,22 @@ export function createPublishAzureAction(options: { export function createPublishBitbucketAction(options: { integrations: ScmIntegrationRegistry; config: Config; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + description?: string | undefined; + defaultBranch?: string | undefined; + repoVisibility?: 'private' | 'public' | undefined; + sourcePath?: string | undefined; + enableLFS?: boolean | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createPublishFileAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public -export function createPublishFileAction(): TemplateAction; +export function createPublishFileAction(): TemplateAction<{ + path: string; +}>; // Warning: (ae-missing-release-tag) "createPublishGithubAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -171,7 +226,23 @@ export function createPublishGithubAction(options: { integrations: ScmIntegrationRegistry; config: Config; githubCredentialsProvider?: GithubCredentialsProvider; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + description?: string | undefined; + access?: string | undefined; + defaultBranch?: string | undefined; + sourcePath?: string | undefined; + requireCodeOwnerReviews?: boolean | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + collaborators?: + | { + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + }[] + | undefined; + token?: string | undefined; + topics?: string[] | undefined; +}>; // Warning: (ae-forgotten-export) The symbol "CreateGithubPullRequestActionOptions" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "createPublishGithubPullRequestAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -181,7 +252,15 @@ export const createPublishGithubPullRequestAction: ({ integrations, githubCredentialsProvider, clientFactory, -}: CreateGithubPullRequestActionOptions) => TemplateAction; +}: CreateGithubPullRequestActionOptions) => TemplateAction<{ + title: string; + branchName: string; + description: string; + repoUrl: string; + targetPath?: string | undefined; + sourcePath?: string | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createPublishGitlabAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -189,14 +268,28 @@ export const createPublishGithubPullRequestAction: ({ export function createPublishGitlabAction(options: { integrations: ScmIntegrationRegistry; config: Config; -}): TemplateAction; +}): TemplateAction<{ + repoUrl: string; + defaultBranch?: string | undefined; + repoVisibility?: 'internal' | 'private' | 'public' | undefined; + sourcePath?: string | undefined; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createPublishGitlabMergeRequestAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const createPublishGitlabMergeRequestAction: (options: { integrations: ScmIntegrationRegistry; -}) => TemplateAction; +}) => TemplateAction<{ + projectid: string; + repoUrl: string; + title: string; + description: string; + branchName: string; + targetPath: string; + token?: string | undefined; +}>; // Warning: (ae-missing-release-tag) "createRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -206,13 +299,9 @@ export function createRouter(options: RouterOptions): Promise; // Warning: (ae-missing-release-tag) "createTemplateAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const createTemplateAction: < - Input extends Partial<{ - [name: string]: JsonValue | Partial | undefined; - }>, ->( - templateAction: TemplateAction, -) => TemplateAction; +export const createTemplateAction: ( + templateAction: TemplateAction, +) => TemplateAction; // @public export type CreateWorkerOptions = { @@ -226,7 +315,6 @@ export type CreateWorkerOptions = { // @public export class DatabaseTaskStore implements TaskStore { - constructor(options: DatabaseTaskStoreOptions); // (undocumented) claimTask(): Promise; // (undocumented) @@ -236,7 +324,7 @@ export class DatabaseTaskStore implements TaskStore { eventBody, }: { taskId: string; - status: Status; + status: TaskStatus; eventBody: JsonObject; }): Promise; // Warning: (ae-forgotten-export) The symbol "DatabaseTaskStoreOptions" needs to be exported by the entry point index.d.ts @@ -245,11 +333,8 @@ export class DatabaseTaskStore implements TaskStore { static create(options: DatabaseTaskStoreOptions): Promise; // (undocumented) createTask( - spec: TaskSpec, - secrets?: TaskSecrets, - ): Promise<{ - taskId: string; - }>; + options: TaskStoreCreateTaskOptions, + ): Promise; // (undocumented) emitLogEvent({ taskId, body }: TaskStoreEmitOptions): Promise; // (undocumented) @@ -268,10 +353,8 @@ export class DatabaseTaskStore implements TaskStore { }>; } -// @public -export type DispatchResult = { - taskId: string; -}; +// @public @deprecated +export type DispatchResult = TaskBrokerDispatchResult; // Warning: (ae-missing-release-tag) "fetchContents" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -344,6 +427,8 @@ export const runCommand: ({ // @public (undocumented) export class ScaffolderEntitiesProcessor implements CatalogProcessor { + // (undocumented) + getProcessorName(): string; // (undocumented) postProcessEntity( entity: Entity, @@ -358,7 +443,7 @@ export class ScaffolderEntitiesProcessor implements CatalogProcessor { export type SerializedTask = { id: string; spec: TaskSpec; - status: Status; + status: TaskStatus; createdAt: string; lastHeartbeatAt?: string; secrets?: TaskSecrets; @@ -373,20 +458,17 @@ export type SerializedTaskEvent = { createdAt: string; }; -// @public -export type Status = - | 'open' - | 'processing' - | 'failed' - | 'cancelled' - | 'completed'; +// @public @deprecated +export type Status = TaskStatus; // @public export interface TaskBroker { // (undocumented) claim(): Promise; // (undocumented) - dispatch(spec: TaskSpec, secrets?: TaskSecrets): Promise; + dispatch( + options: TaskBrokerDispatchOptions, + ): Promise; // (undocumented) get(taskId: string): Promise; // (undocumented) @@ -408,10 +490,24 @@ export interface TaskBroker { vacuumTasks(timeoutS: { timeoutS: number }): Promise; } +// @public +export type TaskBrokerDispatchOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; +}; + +// @public +export type TaskBrokerDispatchResult = { + taskId: string; +}; + +// @public +export type TaskCompletionState = 'failed' | 'completed'; + // @public export interface TaskContext { // (undocumented) - complete(result: CompletedTaskState, metadata?: JsonValue): Promise; + complete(result: TaskCompletionState, metadata?: JsonValue): Promise; // (undocumented) done: boolean; // (undocumented) @@ -430,7 +526,7 @@ export type TaskEventType = 'completion' | 'log'; // @public export class TaskManager implements TaskContext { // (undocumented) - complete(result: CompletedTaskState, metadata?: JsonObject): Promise; + complete(result: TaskCompletionState, metadata?: JsonObject): Promise; // (undocumented) static create( state: TaskState, @@ -451,7 +547,6 @@ export class TaskManager implements TaskContext { // @public export type TaskSecrets = Record & { - token?: string; backstageToken?: string; }; @@ -471,6 +566,14 @@ export interface TaskState { taskId: string; } +// @public +export type TaskStatus = + | 'open' + | 'processing' + | 'failed' + | 'cancelled' + | 'completed'; + // @public export interface TaskStore { // (undocumented) @@ -478,16 +581,13 @@ export interface TaskStore { // (undocumented) completeTask(options: { taskId: string; - status: Status; + status: TaskStatus; eventBody: JsonObject; }): Promise; // (undocumented) createTask( - task: TaskSpec, - secrets?: TaskSecrets, - ): Promise<{ - taskId: string; - }>; + options: TaskStoreCreateTaskOptions, + ): Promise; // (undocumented) emitLogEvent({ taskId, body }: TaskStoreEmitOptions): Promise; // (undocumented) @@ -506,6 +606,17 @@ export interface TaskStore { }>; } +// @public +export type TaskStoreCreateTaskOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; +}; + +// @public +export type TaskStoreCreateTaskResult = { + taskId: string; +}; + // @public export type TaskStoreEmitOptions = { taskId: string; @@ -531,7 +642,7 @@ export class TaskWorker { // Warning: (ae-missing-release-tag) "TemplateAction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export type TemplateAction = { +export type TemplateAction = { id: string; description?: string; schema?: { @@ -546,13 +657,11 @@ export type TemplateAction = { // @public (undocumented) export class TemplateActionRegistry { // (undocumented) - get(actionId: string): TemplateAction; + get(actionId: string): TemplateAction; // (undocumented) - list(): TemplateAction[]; + list(): TemplateAction[]; // (undocumented) - register( - action: TemplateAction, - ): void; + register(action: TemplateAction): void; } // Warning: (ae-missing-release-tag) "TemplateFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index aa4ecf8053..7883284165 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -28,30 +28,5 @@ export interface Config { * The commit message used when new components are created. */ defaultCommitMessage?: string; - /** - * @deprecated Replaced by parameters for the publish:github action - */ - github?: { - [key: string]: string; - }; - /** - * @deprecated Use the Gitlab integration instead - */ - gitlab?: { - api: { [key: string]: string }; - }; - /** - * @deprecated Use the Azure integration instead - */ - azure?: { - baseUrl: string; - api: { [key: string]: string }; - }; - /** - * @deprecated Use the Bitbucket integration instead - */ - bitbucket?: { - api: { [key: string]: string }; - }; }; } diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 3161448562..8c61ee65c4 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "0.15.24", + "version": "0.16.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,26 +24,26 @@ "backstage" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean", + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", "build:assets": "node scripts/build-nunjucks.js" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-backend": "^0.21.3", - "@backstage/plugin-scaffolder-common": "^0.1.3", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.11", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-catalog-backend": "^0.21.4", + "@backstage/plugin-scaffolder-common": "^0.2.0", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.2.0", + "@backstage/types": "^0.1.2", "@gitbeaker/core": "^34.6.0", "@gitbeaker/node": "^35.1.0", "@octokit/webhooks": "^9.14.1", @@ -55,7 +58,6 @@ "git-url-parse": "^11.6.0", "globby": "^11.0.0", "handlebars": "^4.7.6", - "helmet": "^4.0.0", "isbinaryfile": "^4.0.8", "isomorphic-git": "^1.8.0", "jsonschema": "^1.2.6", @@ -73,8 +75,8 @@ "vm2": "^3.9.6" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts deleted file mode 100644 index 430afa5b5d..0000000000 --- a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * 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 { TemplateEntityV1beta2 } from '@backstage/catalog-model'; -import { CatalogApi } from '@backstage/catalog-client'; -import { ConflictError, NotFoundError } from '@backstage/errors'; - -/** - * A catalog client tailored for reading out entity data from the catalog. - */ -export class CatalogEntityClient { - constructor(private readonly catalogClient: CatalogApi) {} - - /** - * Looks up a single template using a template name. - * - * Throws a NotFoundError or ConflictError if 0 or multiple templates are found. - */ - async findTemplate( - templateName: string, - options?: { token?: string }, - ): Promise { - const { items: templates } = (await this.catalogClient.getEntities( - { - filter: { - kind: 'template', - 'metadata.name': templateName, - }, - }, - options, - )) as { items: TemplateEntityV1beta2[] }; - - if (templates.length !== 1) { - if (templates.length > 1) { - throw new ConflictError( - 'Templates lookup resulted in multiple matches', - ); - } else { - throw new NotFoundError('Template not found'); - } - } - - return templates[0]; - } -} diff --git a/plugins/scaffolder-backend/src/lib/index.ts b/plugins/scaffolder-backend/src/lib/index.ts index dbb4348a2c..20096f9c03 100644 --- a/plugins/scaffolder-backend/src/lib/index.ts +++ b/plugins/scaffolder-backend/src/lib/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './catalog'; export * from './templating'; diff --git a/plugins/scaffolder-backend/src/processor/ScaffolderEntitiesProcessor.ts b/plugins/scaffolder-backend/src/processor/ScaffolderEntitiesProcessor.ts index 4f3c13f342..c7d5db38c1 100644 --- a/plugins/scaffolder-backend/src/processor/ScaffolderEntitiesProcessor.ts +++ b/plugins/scaffolder-backend/src/processor/ScaffolderEntitiesProcessor.ts @@ -21,7 +21,6 @@ import { parseEntityRef, RELATION_OWNED_BY, RELATION_OWNER_OF, - entityKindSchemaValidator, } from '@backstage/catalog-model'; import { CatalogProcessor, @@ -30,18 +29,20 @@ import { } from '@backstage/plugin-catalog-backend'; import { TemplateEntityV1beta3, - templateEntityV1beta3Schema, + templateEntityV1beta3Validator, } from '@backstage/plugin-scaffolder-common'; /** @public */ export class ScaffolderEntitiesProcessor implements CatalogProcessor { - private readonly validators = [ - entityKindSchemaValidator(templateEntityV1beta3Schema), - ]; + getProcessorName(): string { + return 'ScaffolderEntitiesProcessor'; + } + + private readonly validators = [templateEntityV1beta3Validator]; async validateEntityKind(entity: Entity): Promise { for (const validator of this.validators) { - if (validator(entity)) { + if (await validator.check(entity)) { return true; } } diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts index cd31db49eb..e546d5bf9a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts @@ -14,13 +14,14 @@ * limitations under the License. */ -import { InputBase, TemplateAction } from './types'; +import { JsonObject } from '@backstage/types'; import { ConflictError, NotFoundError } from '@backstage/errors'; +import { TemplateAction } from './types'; export class TemplateActionRegistry { private readonly actions = new Map>(); - register(action: TemplateAction) { + register(action: TemplateAction) { if (this.actions.has(action.id)) { throw new ConflictError( `Template action with ID '${action.id}' has already been registered`, @@ -29,7 +30,7 @@ export class TemplateActionRegistry { this.actions.set(action.id, action); } - get(actionId: string): TemplateAction { + get(actionId: string): TemplateAction { const action = this.actions.get(actionId); if (!action) { throw new NotFoundError( @@ -39,7 +40,7 @@ export class TemplateActionRegistry { return action; } - list(): TemplateAction[] { + list(): TemplateAction[] { return [...this.actions.values()]; } } diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts index 9612780b12..dd6f29f99b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/write.test.ts @@ -23,7 +23,7 @@ const fsMock = fs as jest.Mocked; import { PassThrough } from 'stream'; import os from 'os'; import { getVoidLogger } from '@backstage/backend-common'; -import { ORIGIN_LOCATION_ANNOTATION } from '@backstage/catalog-model'; +import { ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { createCatalogWriteAction } from './write'; import { resolve as resolvePath } from 'path'; import * as yaml from 'yaml'; @@ -51,7 +51,7 @@ describe('catalog:write', () => { name: 'n', namespace: 'ns', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:https://example.com', + [ANNOTATION_ORIGIN_LOCATION]: 'url:https://example.com', }, }, spec: {}, @@ -79,7 +79,7 @@ describe('catalog:write', () => { name: 'n', namespace: 'ns', annotations: { - [ORIGIN_LOCATION_ANNOTATION]: 'url:https://example.com', + [ANNOTATION_ORIGIN_LOCATION]: 'url:https://example.com', }, }, spec: {}, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 481ab894ec..9df2b7146e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -15,6 +15,7 @@ */ import { ContainerRunner, UrlReader } from '@backstage/backend-common'; +import { JsonObject } from '@backstage/types'; import { CatalogApi } from '@backstage/catalog-client'; import { GithubCredentialsProvider, @@ -47,6 +48,7 @@ import { createGithubWebhookAction, } from './github'; import { TemplateFilter } from '../../../lib'; +import { TemplateAction } from '../types'; export const createBuiltinActions = (options: { reader: UrlReader; @@ -55,7 +57,7 @@ export const createBuiltinActions = (options: { containerRunner?: ContainerRunner; config: Config; additionalTemplateFilters?: Record; -}) => { +}): TemplateAction[] => { const { reader, integrations, @@ -126,5 +128,5 @@ export const createBuiltinActions = (options: { ); } - return actions; + return actions as TemplateAction[]; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts index 38c50afecc..ecd0f33e21 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts @@ -61,7 +61,7 @@ describe('debug:log', () => { const context = { ...mockContext, input: { - listWorkspace: 'true', + listWorkspace: true, }, }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts index 9cac6d5ab8..17f49a5bd4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts @@ -59,7 +59,7 @@ export function createFetchPlainAction(options: { await fetchContents({ reader, integrations, - baseUrl: ctx.baseUrl, + baseUrl: ctx.templateInfo?.baseUrl, fetchUrl: ctx.input.url, outputPath, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts index 6ee8f8ce01..8f641fe2e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts @@ -27,12 +27,18 @@ import { ScmIntegrations } from '@backstage/integration'; import { PassThrough } from 'stream'; import { fetchContents } from './helpers'; import { ActionContext, TemplateAction } from '../../types'; -import { createFetchTemplateAction, FetchTemplateInput } from './template'; +import { createFetchTemplateAction } from './template'; jest.mock('./helpers', () => ({ fetchContents: jest.fn(), })); +type FetchTemplateInput = ReturnType< + typeof createFetchTemplateAction +> extends TemplateAction + ? U + : never; + const realFiles = Object.fromEntries( [ resolvePackagePath( @@ -69,7 +75,10 @@ describe('fetch:template', () => { const logger = getVoidLogger(); const mockContext = (inputPatch: Partial = {}) => ({ - baseUrl: 'base-url', + templateInfo: { + baseUrl: 'base-url', + entityRef: 'template:default/test-template', + }, input: { url: './skeleton', targetPath: './target', @@ -193,7 +202,7 @@ describe('fetch:template', () => { it('uses fetchContents to retrieve the template content', () => { expect(mockFetchContents).toHaveBeenCalledWith( expect.objectContaining({ - baseUrl: context.baseUrl, + baseUrl: context.templateInfo?.baseUrl, fetchUrl: context.input.url, }), ); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts index 32a3a84070..a8ba9ac19f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.ts @@ -28,22 +28,6 @@ import { SecureTemplater, } from '../../../../lib/templating/SecureTemplater'; -type CookieCompatInput = { - copyWithoutRender?: string[]; - cookiecutterCompat?: boolean; -}; - -type ExtensionInput = { - templateFileExtension?: string | boolean; -}; - -export type FetchTemplateInput = { - url: string; - targetPath?: string; - values: any; -} & CookieCompatInput & - ExtensionInput; - export function createFetchTemplateAction(options: { reader: UrlReader; integrations: ScmIntegrations; @@ -51,7 +35,16 @@ export function createFetchTemplateAction(options: { }) { const { reader, integrations, additionalTemplateFilters } = options; - return createTemplateAction({ + return createTemplateAction<{ + url: string; + targetPath?: string; + values: any; + templateFileExtension?: string | boolean; + + // Cookiecutter compat options + copyWithoutRender?: string[]; + cookiecutterCompat?: boolean; + }>({ id: 'fetch:template', description: "Downloads a skeleton, templates variables into file and directory names and content, and places the result in the workspace, or optionally in a subdirectory specified by the 'targetPath' input option.", @@ -142,7 +135,7 @@ export function createFetchTemplateAction(options: { await fetchContents({ reader, integrations, - baseUrl: ctx.baseUrl, + baseUrl: ctx.templateInfo?.baseUrl, fetchUrl: ctx.input.url, outputPath: templateDir, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts index ba8a145721..713de5b0ad 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts @@ -61,28 +61,28 @@ describe('fs:delete', () => { await expect( action.handler({ ...mockContext, - input: { files: undefined }, + input: { files: undefined } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: {} }, + input: { files: {} } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: '' }, + input: { files: '' } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: null }, + input: { files: null } as any, }), ).rejects.toThrow(/files must be an Array/); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts index 8452735083..b12e4269c2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts @@ -76,28 +76,28 @@ describe('fs:rename', () => { await expect( action.handler({ ...mockContext, - input: { files: undefined }, + input: { files: undefined } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: {} }, + input: { files: {} } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: '' }, + input: { files: '' } as any, }), ).rejects.toThrow(/files must be an Array/); await expect( action.handler({ ...mockContext, - input: { files: null }, + input: { files: null } as any, }), ).rejects.toThrow(/files must be an Array/); }); @@ -106,21 +106,21 @@ describe('fs:rename', () => { await expect( action.handler({ ...mockContext, - input: { files: ['old.md'] }, + input: { files: ['old.md'] } as any, }), ).rejects.toThrow(/each file must have a from and to property/); await expect( action.handler({ ...mockContext, - input: { files: [{ from: 'old.md' }] }, + input: { files: [{ from: 'old.md' }] } as any, }), ).rejects.toThrow(/each file must have a from and to property/); await expect( action.handler({ ...mockContext, - input: { files: [{ to: 'new.md' }] }, + input: { files: [{ to: 'new.md' }] } as any, }), ).rejects.toThrow(/each file must have a from and to property/); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts index 4bdba96750..c3e128cec5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts @@ -17,16 +17,16 @@ import { createTemplateAction } from '../../createTemplateAction'; import { resolveSafeChildPath } from '@backstage/backend-common'; import { InputError } from '@backstage/errors'; -import { JsonObject } from '@backstage/types'; import fs from 'fs-extra'; -interface FilesToRename extends JsonObject { - from: string; - to: string; -} - export const createFilesystemRenameAction = () => { - return createTemplateAction<{ files: FilesToRename }>({ + return createTemplateAction<{ + files: Array<{ + from: string; + to: string; + overwrite?: boolean; + }>; + }>({ id: 'fs:rename', description: 'Renames files and directories within the workspace', schema: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts index 660c7793f2..0c93ae1dd5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts @@ -23,8 +23,6 @@ import { OctokitProvider } from './OctokitProvider'; import { emitterEventNames } from '@octokit/webhooks'; import { assertError } from '@backstage/errors'; -type ContentType = 'form' | 'json'; - export function createGithubWebhookAction(options: { integrations: ScmIntegrationRegistry; defaultWebhookSecret?: string; @@ -45,7 +43,7 @@ export function createGithubWebhookAction(options: { webhookSecret?: string; events?: string[]; active?: boolean; - contentType?: ContentType; + contentType?: 'form' | 'json'; insecureSsl?: boolean; token?: string; }>({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 92b578d385..9303b5e487 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -58,7 +58,9 @@ export const runCommand = async ({ process.on('close', code => { if (code !== 0) { - return reject(`Command ${command} failed, exit code: ${code}`); + return reject( + new Error(`Command ${command} failed, exit code: ${code}`), + ); } return resolve(); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 3d14710f3e..5493219d57 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -51,7 +51,7 @@ describe('publish:bitbucket', () => { const mockContext = { input: { repoUrl: 'bitbucket.org?workspace=workspace&project=project&repo=repo', - repoVisibility: 'private', + repoVisibility: 'private' as const, }, workspacePath: 'lol', logger: getVoidLogger(), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index 8ba8592642..47ebce0550 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -29,7 +29,7 @@ const createBitbucketCloudRepository = async (opts: { workspace: string; project: string; repo: string; - description: string; + description?: string; repoVisibility: 'private' | 'public'; authorization: string; }) => { @@ -91,7 +91,7 @@ const createBitbucketServerRepository = async (opts: { host: string; project: string; repo: string; - description: string; + description?: string; repoVisibility: 'private' | 'public'; authorization: string; apiBaseUrl?: string; @@ -200,11 +200,11 @@ export function createPublishBitbucketAction(options: { return createTemplateAction<{ repoUrl: string; - description: string; + description?: string; defaultBranch?: string; - repoVisibility: 'private' | 'public'; + repoVisibility?: 'private' | 'public'; sourcePath?: string; - enableLFS: boolean; + enableLFS?: boolean; token?: string; }>({ id: 'publish:bitbucket', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 5467ca651c..1e58635bbe 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -52,7 +52,7 @@ describe('publish:github', () => { input: { repoUrl: 'github.com?repo=repo&owner=owner', description: 'description', - repoVisibility: 'private', + repoVisibility: 'private' as const, access: 'owner/blam', }, workspacePath: 'lol', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 139fad04d4..cabe40986f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -28,9 +28,6 @@ import { Config } from '@backstage/config'; import { OctokitProvider } from '../github/OctokitProvider'; import { assertError } from '@backstage/errors'; -type Permission = 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; -type Collaborator = { access: Permission; username: string }; - export function createPublishGithubAction(options: { integrations: ScmIntegrationRegistry; config: Config; @@ -50,8 +47,11 @@ export function createPublishGithubAction(options: { defaultBranch?: string; sourcePath?: string; requireCodeOwnerReviews?: boolean; - repoVisibility: 'private' | 'internal' | 'public'; - collaborators: Collaborator[]; + repoVisibility?: 'private' | 'internal' | 'public'; + collaborators?: Array<{ + username: string; + access: 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; + }>; token?: string; topics?: string[]; }>({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts index 20ea4b03da..64d3bc41de 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts @@ -28,13 +28,18 @@ import { ActionContext, TemplateAction } from '../../types'; import { ClientFactoryInput, createPublishGithubPullRequestAction, - GithubPullRequestActionInput, PullRequestCreator, } from './githubPullRequest'; const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; const workspacePath = resolvePath(root, 'my-workspace'); +type GithubPullRequestActionInput = ReturnType< + typeof createPublishGithubPullRequestAction +> extends TemplateAction + ? U + : never; + describe('createPublishGithubPullRequestAction', () => { let instance: TemplateAction; let fakeClient: PullRequestCreator; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index 80333c4966..c329b6b6f3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -48,16 +48,6 @@ export type PullRequestCreatorConstructor = ( octokit: Octokit, ) => PullRequestCreator; -export type GithubPullRequestActionInput = { - title: string; - branchName: string; - description: string; - repoUrl: string; - targetPath?: string; - sourcePath?: string; - token?: string; -}; - export type ClientFactoryInput = { integrations: ScmIntegrationRegistry; githubCredentialsProvider?: GithubCredentialsProvider; @@ -122,7 +112,15 @@ export const createPublishGithubPullRequestAction = ({ githubCredentialsProvider, clientFactory = defaultClientFactory, }: CreateGithubPullRequestActionOptions) => { - return createTemplateAction({ + return createTemplateAction<{ + title: string; + branchName: string; + description: string; + repoUrl: string; + targetPath?: string; + sourcePath?: string; + token?: string; + }>({ id: 'publish:github:pull-request', schema: { input: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index a32fea8830..db4ad5a019 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -45,7 +45,7 @@ describe('publish:gitlab', () => { const mockContext = { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', - repoVisibility: 'private', + repoVisibility: 'private' as const, }, workspacePath: 'lol', logger: getVoidLogger(), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 48979306b1..a3c1919b63 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -31,7 +31,7 @@ export function createPublishGitlabAction(options: { return createTemplateAction<{ repoUrl: string; defaultBranch?: string; - repoVisibility: 'private' | 'internal' | 'public'; + repoVisibility?: 'private' | 'internal' | 'public'; sourcePath?: string; token?: string; }>({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts index bf687268c3..e04eb5cdb5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.ts @@ -24,22 +24,20 @@ import { InputError } from '@backstage/errors'; import { parseRepoUrl } from './util'; import { resolveSafeChildPath } from '@backstage/backend-common'; -export type GitlabMergeRequestActionInput = { - projectid: string; - repoUrl: string; - title: string; - description: string; - branchName: string; - targetPath: string; - token?: string; -}; - export const createPublishGitlabMergeRequestAction = (options: { integrations: ScmIntegrationRegistry; }) => { const { integrations } = options; - return createTemplateAction({ + return createTemplateAction<{ + projectid: string; + repoUrl: string; + title: string; + description: string; + branchName: string; + targetPath: string; + token?: string; + }>({ id: 'publish:gitlab:merge-request', schema: { input: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/createTemplateAction.ts b/plugins/scaffolder-backend/src/scaffolder/actions/createTemplateAction.ts index a741900f9d..243f39e070 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/createTemplateAction.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/createTemplateAction.ts @@ -14,11 +14,12 @@ * limitations under the License. */ -import { InputBase, TemplateAction } from './types'; +import { JsonObject } from '@backstage/types'; +import { TemplateAction } from './types'; -export const createTemplateAction = ( - templateAction: TemplateAction, -): TemplateAction => { +export const createTemplateAction = ( + templateAction: TemplateAction, +): TemplateAction => { // TODO(blam): Can add some more validation here to validate the action later on return templateAction; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts index 4b842e8c5c..b2227426b8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts @@ -19,25 +19,17 @@ import { Writable } from 'stream'; import { JsonValue, JsonObject } from '@backstage/types'; import { Schema } from 'jsonschema'; import { TaskSecrets, TemplateMetadata } from '../tasks/types'; +import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; -type PartialJsonObject = Partial; -type PartialJsonValue = PartialJsonObject | JsonValue | undefined; -export type InputBase = Partial<{ [name: string]: PartialJsonValue }>; - -export type ActionContext = { +export type ActionContext = { /** * Base URL for the location of the task spec, typically the url of the source entity file. + * @deprecated please use templateInfo.baseUrl instead */ baseUrl?: string; logger: Logger; logStream: Writable; - - /** - * User token forwarded from initial request, for use in subsequent api requests - * @deprecated use `secrets.backstageToken` instead - */ - token?: string | undefined; secrets?: TaskSecrets; workspacePath: string; input: Input; @@ -48,10 +40,14 @@ export type ActionContext = { */ createTemporaryDirectory(): Promise; + /** + * @deprecated please use templateInfo instead + */ metadata?: TemplateMetadata; + templateInfo?: TemplateInfo; }; -export type TemplateAction = { +export type TemplateAction = { id: string; description?: string; schema?: { diff --git a/plugins/scaffolder-backend/src/scaffolder/index.ts b/plugins/scaffolder-backend/src/scaffolder/index.ts index e055223d8c..0c6b5e01cc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/index.ts @@ -13,5 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export * from './actions'; export * from './tasks'; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index dcda3b921e..389ecae5c6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -22,13 +22,13 @@ import { v4 as uuid } from 'uuid'; import { SerializedTaskEvent, SerializedTask, - Status, + TaskStatus, TaskEventType, - TaskSecrets, - TaskSpec, TaskStore, TaskStoreEmitOptions, TaskStoreListEventsOptions, + TaskStoreCreateTaskOptions, + TaskStoreCreateTaskResult, } from './types'; import { DateTime } from 'luxon'; @@ -40,7 +40,7 @@ const migrationsDir = resolvePackagePath( export type RawDbTaskRow = { id: string; spec: string; - status: Status; + status: TaskStatus; last_heartbeat_at?: string; created_at: string; secrets?: string | null; @@ -80,7 +80,7 @@ export class DatabaseTaskStore implements TaskStore { return new DatabaseTaskStore(options); } - constructor(options: DatabaseTaskStoreOptions) { + private constructor(options: DatabaseTaskStoreOptions) { this.db = options.database; } @@ -108,14 +108,13 @@ export class DatabaseTaskStore implements TaskStore { } async createTask( - spec: TaskSpec, - secrets?: TaskSecrets, - ): Promise<{ taskId: string }> { + options: TaskStoreCreateTaskOptions, + ): Promise { const taskId = uuid(); await this.db('tasks').insert({ id: taskId, - spec: JSON.stringify(spec), - secrets: secrets ? JSON.stringify(secrets) : undefined, + spec: JSON.stringify(options.spec), + secrets: options.secrets ? JSON.stringify(options.secrets) : undefined, status: 'open', }); return { taskId }; @@ -202,7 +201,7 @@ export class DatabaseTaskStore implements TaskStore { eventBody, }: { taskId: string; - status: Status; + status: TaskStatus; eventBody: JsonObject; }): Promise { let oldStatus: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.test.ts index 9b05c43831..9f4135b3d1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.test.ts @@ -94,7 +94,7 @@ describe('LegacyWorkflowRunner', () => { }); it('should pass metadata through', async () => { - const templateName = 'template name'; + const entityRef = `template:default/templateName`; const task = createMockTaskWithSpec({ apiVersion: 'backstage.io/v1beta2', steps: [ @@ -107,13 +107,13 @@ describe('LegacyWorkflowRunner', () => { ], output: {}, values: {}, - metadata: { name: templateName }, + templateInfo: { entityRef }, }); await runner.execute(task); - expect(fakeActionHandler.mock.calls[0][0].metadata).toEqual({ - name: templateName, + expect(fakeActionHandler.mock.calls[0][0].templateInfo).toEqual({ + entityRef, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.ts index 91c82edebb..e525e6bd14 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/HandlebarsWorkflowRunner.ts @@ -225,19 +225,12 @@ export class HandlebarsWorkflowRunner implements WorkflowRunner { input: JSON.stringify(input, null, 2), }); - if (!task.spec.metadata) { - console.warn( - 'DEPRECATION NOTICE: metadata is undefined. metadata will be required in the future.', - ); - } - await action.handler({ + // deprecated in favor of templateInfo.baseUrl baseUrl: task.spec.baseUrl, logger: taskLogger, logStream: stream, input, - // this token is deprecated, and will be removed in favour of secrets.backstageToken instead. - token: task.secrets?.token, secrets: task.secrets ?? {}, workspacePath, async createTemporaryDirectory() { @@ -250,7 +243,9 @@ export class HandlebarsWorkflowRunner implements WorkflowRunner { output(name: string, value: JsonValue) { stepOutputs[name] = value; }, + // deprecated in favor of templateInfo metadata: task.spec.metadata, + templateInfo: task.spec.templateInfo, }); // Remove all temporary directories that were created when executing the action diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 1597c575ac..b66c69ee17 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -163,7 +163,7 @@ describe('DefaultWorkflowRunner', () => { }); it('should pass metadata through', async () => { - const templateName = 'template name'; + const entityRef = `template:default/templateName`; const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', parameters: {}, @@ -176,13 +176,13 @@ describe('DefaultWorkflowRunner', () => { input: { foo: 1 }, }, ], - metadata: { name: templateName }, + templateInfo: { entityRef }, }); await runner.execute(task); - expect(fakeActionHandler.mock.calls[0][0].metadata).toEqual({ - name: templateName, + expect(fakeActionHandler.mock.calls[0][0].templateInfo).toEqual({ + entityRef, }); }); @@ -203,13 +203,15 @@ describe('DefaultWorkflowRunner', () => { ], }, { - token: fakeToken, + backstageToken: fakeToken, }, ); await runner.execute(task); - expect(fakeActionHandler.mock.calls[0][0].token).toEqual(fakeToken); + expect(fakeActionHandler.mock.calls[0][0].secrets).toEqual( + expect.objectContaining({ backstageToken: fakeToken }), + ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 889e94d000..b1177ca49c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -258,17 +258,10 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const tmpDirs = new Array(); const stepOutput: { [outputName: string]: JsonValue } = {}; - if (!task.spec.metadata) { - console.warn( - 'DEPRECATION NOTICE: metadata is undefined. metadata will be required in the future.', - ); - } - await action.handler({ + // deprecated in favourof templateInfo.baseUrl baseUrl: task.spec.baseUrl, input, - // this token is deprecated, and will be removed in favour of secrets.backstageToken instead. - token: task.secrets?.token, secrets: task.secrets ?? {}, logger: taskLogger, logStream: streamLogger, @@ -283,7 +276,9 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { output(name: string, value: JsonValue) { stepOutput[name] = value; }, + // deprecated in favour of templateInfo metadata: task.spec.metadata, + templateInfo: task.spec.templateInfo, }); // Remove all temporary directories that were created when executing the action diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts index 130f6ced13..daf444cdd8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.test.ts @@ -38,7 +38,7 @@ async function createStore(): Promise { describe('StorageTaskBroker', () => { let storage: DatabaseTaskStore; - const fakeSecrets = { token: 'secret' } as TaskSecrets; + const fakeSecrets = { backstageToken: 'secret' } as TaskSecrets; beforeAll(async () => { storage = await createStore(); @@ -47,7 +47,7 @@ describe('StorageTaskBroker', () => { const logger = getVoidLogger(); it('should claim a dispatched work item', async () => { const broker = new StorageTaskBroker(storage, logger); - await broker.dispatch({} as TaskSpec); + await broker.dispatch({ spec: {} as TaskSpec }); await expect(broker.claim()).resolves.toEqual(expect.any(TaskManager)); }); @@ -57,15 +57,15 @@ describe('StorageTaskBroker', () => { await expect(Promise.race([promise, 'waiting'])).resolves.toBe('waiting'); - await broker.dispatch({} as TaskSpec); + await broker.dispatch({ spec: {} as TaskSpec }); await expect(promise).resolves.toEqual(expect.any(TaskManager)); }); it('should dispatch multiple items and claim them in order', async () => { const broker = new StorageTaskBroker(storage, logger); - await broker.dispatch({ steps: [{ id: 'a' }] } as TaskSpec); - await broker.dispatch({ steps: [{ id: 'b' }] } as TaskSpec); - await broker.dispatch({ steps: [{ id: 'c' }] } as TaskSpec); + await broker.dispatch({ spec: { steps: [{ id: 'a' }] } as TaskSpec }); + await broker.dispatch({ spec: { steps: [{ id: 'b' }] } as TaskSpec }); + await broker.dispatch({ spec: { steps: [{ id: 'c' }] } as TaskSpec }); const taskA = await broker.claim(); const taskB = await broker.claim(); @@ -80,14 +80,14 @@ describe('StorageTaskBroker', () => { it('should store secrets', async () => { const broker = new StorageTaskBroker(storage, logger); - await broker.dispatch({} as TaskSpec, fakeSecrets); + await broker.dispatch({ spec: {} as TaskSpec, secrets: fakeSecrets }); const task = await broker.claim(); expect(task.secrets).toEqual(fakeSecrets); }, 10000); it('should complete a task', async () => { const broker = new StorageTaskBroker(storage, logger); - const dispatchResult = await broker.dispatch({} as TaskSpec); + const dispatchResult = await broker.dispatch({ spec: {} as TaskSpec }); const task = await broker.claim(); await task.complete('completed'); const taskRow = await storage.getTask(dispatchResult.taskId); @@ -96,7 +96,10 @@ describe('StorageTaskBroker', () => { it('should remove secrets after picking up a task', async () => { const broker = new StorageTaskBroker(storage, logger); - const dispatchResult = await broker.dispatch({} as TaskSpec, fakeSecrets); + const dispatchResult = await broker.dispatch({ + spec: {} as TaskSpec, + secrets: fakeSecrets, + }); await broker.claim(); const taskRow = await storage.getTask(dispatchResult.taskId); @@ -105,7 +108,7 @@ describe('StorageTaskBroker', () => { it('should fail a task', async () => { const broker = new StorageTaskBroker(storage, logger); - const dispatchResult = await broker.dispatch({} as TaskSpec); + const dispatchResult = await broker.dispatch({ spec: {} as TaskSpec }); const task = await broker.claim(); await task.complete('failed'); const taskRow = await storage.getTask(dispatchResult.taskId); @@ -116,7 +119,7 @@ describe('StorageTaskBroker', () => { const broker1 = new StorageTaskBroker(storage, logger); const broker2 = new StorageTaskBroker(storage, logger); - const { taskId } = await broker1.dispatch({} as TaskSpec); + const { taskId } = await broker1.dispatch({ spec: {} as TaskSpec }); const logPromise = new Promise(resolve => { const observedEvents = new Array(); @@ -155,7 +158,7 @@ describe('StorageTaskBroker', () => { it('should heartbeat', async () => { const broker = new StorageTaskBroker(storage, logger); - const { taskId } = await broker.dispatch({} as TaskSpec); + const { taskId } = await broker.dispatch({ spec: {} as TaskSpec }); const task = await broker.claim(); const initialTask = await storage.getTask(taskId); @@ -173,7 +176,7 @@ describe('StorageTaskBroker', () => { it('should be update the status to failed if heartbeat fails', async () => { const broker = new StorageTaskBroker(storage, logger); - const { taskId } = await broker.dispatch({} as TaskSpec); + const { taskId } = await broker.dispatch({ spec: {} as TaskSpec }); const task = await broker.claim(); jest diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index 7e7ebe5436..49c1056727 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -17,16 +17,16 @@ import { JsonObject } from '@backstage/types'; import { assertError } from '@backstage/errors'; import { Logger } from 'winston'; import { - CompletedTaskState, + TaskCompletionState, TaskContext, TaskSecrets, TaskSpec, TaskStore, TaskBroker, - DispatchResult, SerializedTaskEvent, SerializedTask, } from './types'; +import { TaskBrokerDispatchOptions } from '.'; /** * TaskManager @@ -75,7 +75,7 @@ export class TaskManager implements TaskContext { } async complete( - result: CompletedTaskState, + result: TaskCompletionState, metadata?: JsonObject, ): Promise { await this.storage.completeTask({ @@ -155,10 +155,9 @@ export class StorageTaskBroker implements TaskBroker { } async dispatch( - spec: TaskSpec, - secrets?: TaskSecrets, - ): Promise { - const taskRow = await this.storage.createTask(spec, secrets); + options: TaskBrokerDispatchOptions, + ): Promise<{ taskId: string }> { + const taskRow = await this.storage.createTask(options); this.signalDispatch(); return { taskId: taskRow.taskId, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.test.ts index 9b6baf3b84..9ff6b9c8a1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.test.ts @@ -91,12 +91,14 @@ describe('TaskWorker', () => { }); await broker.dispatch({ - apiVersion: 'backstage.io/v1beta2', - steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], - output: { - result: '{{ steps.test.output.testOutput }}', + spec: { + apiVersion: 'backstage.io/v1beta2', + steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], + output: { + result: '{{ steps.test.output.testOutput }}', + }, + values: {}, }, - values: {}, }); const task = await broker.claim(); @@ -122,12 +124,14 @@ describe('TaskWorker', () => { }); await broker.dispatch({ - apiVersion: 'scaffolder.backstage.io/v1beta3', - steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], - output: { - result: '{{ steps.test.output.testOutput }}', + spec: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], + output: { + result: '{{ steps.test.output.testOutput }}', + }, + parameters: {}, }, - parameters: {}, }); const task = await broker.claim(); @@ -151,12 +155,14 @@ describe('TaskWorker', () => { }); const { taskId } = await broker.dispatch({ - apiVersion: 'scaffolder.backstage.io/v1beta3', - steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], - output: { - result: '{{ steps.test.output.testOutput }}', + spec: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + steps: [{ id: 'test', name: 'test', action: 'not-found-action' }], + output: { + result: '{{ steps.test.output.testOutput }}', + }, + parameters: {}, }, - parameters: {}, }); const task = await broker.claim(); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/index.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/index.ts index f563a08df6..89404d3390 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/index.ts @@ -21,6 +21,7 @@ export type { CreateWorkerOptions } from './TaskWorker'; export type { TaskSecrets, TaskSpec, + TaskCompletionState, CompletedTaskState, TaskStoreEmitOptions, TaskStoreListEventsOptions, @@ -29,10 +30,15 @@ export type { TaskSpecV1beta2, TaskSpecV1beta3, Status, + TaskStatus, TaskEventType, TaskBroker, TaskContext, TaskStore, DispatchResult, + TaskBrokerDispatchResult, + TaskBrokerDispatchOptions, + TaskStoreCreateTaskOptions, + TaskStoreCreateTaskResult, TemplateMetadata, } from './types'; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts index 8caee87f57..c75b85f7b5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/types.ts @@ -32,11 +32,11 @@ export type { }; /** - * Status + * The status of each step of the Task * * @public */ -export type Status = +export type TaskStatus = | 'open' | 'processing' | 'failed' @@ -44,11 +44,27 @@ export type Status = | 'completed'; /** - * CompletedTaskState + * The status of each step of the Task + * + * @public + * @deprecated use TaskStatus instead + */ +export type Status = TaskStatus; + +/** + * The state of a completed task. * * @public */ -export type CompletedTaskState = 'failed' | 'completed'; +export type TaskCompletionState = 'failed' | 'completed'; + +/** + * The state of a completed task. + * + * @public + * @deprecated use TaskCompletionState instead + */ +export type CompletedTaskState = TaskCompletionState; /** * SerializedTask @@ -58,7 +74,7 @@ export type CompletedTaskState = 'failed' | 'completed'; export type SerializedTask = { id: string; spec: TaskSpec; - status: Status; + status: TaskStatus; createdAt: string; lastHeartbeatAt?: string; secrets?: TaskSecrets; @@ -90,19 +106,36 @@ export type SerializedTaskEvent = { * @public */ export type TaskSecrets = Record & { - /** @deprecated Use `backstageToken` instead */ - token?: string; backstageToken?: string; }; +/** + * The result of {@link TaskBroker.dispatch} + * + * @public + */ +export type TaskBrokerDispatchResult = { + taskId: string; +}; + +/** + * The options passed to {@link TaskBroker.dispatch} + * Currently a spec and optional secrets + * + * @public + */ +export type TaskBrokerDispatchOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; +}; + /** * DispatchResult * * @public + * @deprecated use TaskBrokerDispatchResult instead */ -export type DispatchResult = { - taskId: string; -}; +export type DispatchResult = TaskBrokerDispatchResult; /** * Task @@ -114,7 +147,7 @@ export interface TaskContext { secrets?: TaskSecrets; done: boolean; emitLog(message: string, metadata?: JsonValue): Promise; - complete(result: CompletedTaskState, metadata?: JsonValue): Promise; + complete(result: TaskCompletionState, metadata?: JsonValue): Promise; getWorkspaceName(): Promise; } @@ -125,7 +158,9 @@ export interface TaskContext { */ export interface TaskBroker { claim(): Promise; - dispatch(spec: TaskSpec, secrets?: TaskSecrets): Promise; + dispatch( + options: TaskBrokerDispatchOptions, + ): Promise; vacuumTasks(timeoutS: { timeoutS: number }): Promise; observe( options: { @@ -160,6 +195,23 @@ export type TaskStoreListEventsOptions = { after?: number | undefined; }; +/** + * The options passed to {@link TaskStore.createTask} + * @public + */ +export type TaskStoreCreateTaskOptions = { + spec: TaskSpec; + secrets?: TaskSecrets; +}; + +/** + * The response from {@link TaskStore.createTask} + * @public + */ +export type TaskStoreCreateTaskResult = { + taskId: string; +}; + /** * TaskStore * @@ -167,14 +219,13 @@ export type TaskStoreListEventsOptions = { */ export interface TaskStore { createTask( - task: TaskSpec, - secrets?: TaskSecrets, - ): Promise<{ taskId: string }>; + options: TaskStoreCreateTaskOptions, + ): Promise; getTask(taskId: string): Promise; claimTask(): Promise; completeTask(options: { taskId: string; - status: Status; + status: TaskStatus; eventBody: JsonObject; }): Promise; heartbeatTask(taskId: string): Promise; diff --git a/plugins/scaffolder-backend/src/service/helpers.ts b/plugins/scaffolder-backend/src/service/helpers.ts index 6741ab3379..5cfc58d586 100644 --- a/plugins/scaffolder-backend/src/service/helpers.ts +++ b/plugins/scaffolder-backend/src/service/helpers.ts @@ -14,14 +14,21 @@ * limitations under the License. */ +import { CatalogApi } from '@backstage/catalog-client'; import { Entity, - LOCATION_ANNOTATION, - parseLocationReference, - SOURCE_LOCATION_ANNOTATION, + ANNOTATION_LOCATION, + parseLocationRef, + ANNOTATION_SOURCE_LOCATION, + EntityRef, + parseEntityRef, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { assertError } from '@backstage/errors'; +import { assertError, ConflictError, NotFoundError } from '@backstage/errors'; +import { + TemplateEntityV1beta2, + TemplateEntityV1beta3, +} from '@backstage/plugin-scaffolder-common'; import fs from 'fs-extra'; import os from 'os'; import { Logger } from 'winston'; @@ -59,15 +66,15 @@ export async function getWorkingDirectory( * For file locations this will return a `file://` URL. */ export function getEntityBaseUrl(entity: Entity): string | undefined { - let location = entity.metadata.annotations?.[SOURCE_LOCATION_ANNOTATION]; + let location = entity.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION]; if (!location) { - location = entity.metadata.annotations?.[LOCATION_ANNOTATION]; + location = entity.metadata.annotations?.[ANNOTATION_LOCATION]; } if (!location) { return undefined; } - const { type, target } = parseLocationReference(location); + const { type, target } = parseLocationRef(location); if (type === 'url') { return target; } else if (type === 'file') { @@ -78,3 +85,49 @@ export function getEntityBaseUrl(entity: Entity): string | undefined { // what the url is pointing to makes sense to use as a baseUrl return undefined; } + +/** + * Will use the provided CatalogApi to go find the template entity ref that is provided with and additional token + * Returns the first matching template, throws a NotFoundError or ConflictError if 0 or multiple templates are found. + */ +export async function findTemplate({ + entityRef, + token, + catalogApi, +}: { + entityRef: EntityRef; + token?: string; + catalogApi: CatalogApi; +}): Promise { + const parsedEntityRef = parseEntityRef(entityRef, { + defaultKind: 'template', + defaultNamespace: 'default', + }); + const { items } = await catalogApi.getEntities( + { + filter: { + kind: 'template', + 'metadata.name': parsedEntityRef.name, + 'metadata.namespace': parsedEntityRef.namespace, + }, + }, + { + token, + }, + ); + + const templates = items.filter( + (entity): entity is TemplateEntityV1beta3 | TemplateEntityV1beta2 => + entity.kind === 'Template', + ); + + if (templates.length !== 1) { + if (templates.length > 1) { + throw new ConflictError('Templates lookup resulted in multiple matches'); + } else { + throw new NotFoundError('Template not found'); + } + } + + return templates[0]; +} diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index d8ba15279f..b20dfa5d24 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -36,7 +36,7 @@ import { UrlReaders, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; -import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; @@ -182,7 +182,7 @@ describe('createRouter', () => { spec: {} as any, status: 'completed', createdAt: '', - secrets: { token: 'secret' }, + secrets: { backstageToken: 'secret' }, }); const response = await request(app).get(`/v2/tasks/a-random-id`); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 85ed8a60ab..371fc47dc2 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -20,16 +20,22 @@ import { UrlReader, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; -import { Entity, TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { InputError, NotFoundError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; -import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { + TemplateEntityV1beta2, + TemplateEntityV1beta3, + TaskSpecV1beta3, + TaskSpecV1beta2, +} from '@backstage/plugin-scaffolder-common'; import express from 'express'; import Router from 'express-promise-router'; import { validate } from 'jsonschema'; import { Logger } from 'winston'; -import { CatalogEntityClient, TemplateFilter } from '../lib'; +import { TemplateFilter } from '../lib'; import { createBuiltinActions, DatabaseTaskStore, @@ -40,7 +46,7 @@ import { TemplateActionRegistry, } from '../scaffolder'; import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker'; -import { getEntityBaseUrl, getWorkingDirectory } from './helpers'; +import { getEntityBaseUrl, getWorkingDirectory, findTemplate } from './helpers'; /** * RouterOptions @@ -89,7 +95,6 @@ export async function createRouter( const logger = parentLogger.child({ plugin: 'scaffolder' }); const workingDirectory = await getWorkingDirectory(config, logger); - const entityClient = new CatalogEntityClient(catalogClient); const integrations = ScmIntegrations.fromConfig(config); let taskBroker: TaskBroker; @@ -148,7 +153,9 @@ export async function createRouter( ); } - const template = await entityClient.findTemplate(name, { + const template = await findTemplate({ + catalogApi: catalogClient, + entityRef: { kind, namespace, name }, token: getBearerToken(req.headers.authorization), }); if (isSupportedTemplate(template)) { @@ -181,18 +188,34 @@ export async function createRouter( }) .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; + const { kind, namespace } = { kind: 'template', namespace: 'default' }; const values = req.body.values; const token = getBearerToken(req.headers.authorization); - const template = await entityClient.findTemplate(templateName, { - token, + const template = await findTemplate({ + catalogApi: catalogClient, + entityRef: { + name: templateName, + kind, + namespace, + }, + token: getBearerToken(req.headers.authorization), }); let taskSpec: TaskSpec; if (isSupportedTemplate(template)) { + if (template.apiVersion === 'backstage.io/v1beta2') { + logger.warn( + `Scaffolding ${stringifyEntityRef( + template, + )} with deprecated apiVersion ${ + template.apiVersion + }. Please migrate the template to backstage.io/v1beta3. https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3`, + ); + } + for (const parameters of [template.spec.parameters ?? []].flat()) { const result = validate(values, parameters); - if (!result.valid) { res.status(400).json({ errors: result.errors }); return; @@ -201,32 +224,40 @@ export async function createRouter( const baseUrl = getEntityBaseUrl(template); + const baseTaskSpec = { + baseUrl, + steps: template.spec.steps.map((step, index) => ({ + ...step, + id: step.id ?? `step-${index + 1}`, + name: step.name ?? step.action, + })), + output: template.spec.output ?? {}, + + // deprecated in favour of templateInfo + metadata: { name: template.metadata?.name }, + + templateInfo: { + entityRef: stringifyEntityRef({ + kind, + namespace, + name: template.metadata?.name, + }), + baseUrl, + }, + }; + taskSpec = template.apiVersion === 'backstage.io/v1beta2' - ? { + ? ({ + ...baseTaskSpec, apiVersion: template.apiVersion, - baseUrl, values, - steps: template.spec.steps.map((step, index) => ({ - ...step, - id: step.id ?? `step-${index + 1}`, - name: step.name ?? step.action, - })), - output: template.spec.output ?? {}, - metadata: { name: template.metadata?.name }, - } - : { + } as TaskSpecV1beta2) + : ({ + ...baseTaskSpec, apiVersion: template.apiVersion, - baseUrl, parameters: values, - steps: template.spec.steps.map((step, index) => ({ - ...step, - id: step.id ?? `step-${index + 1}`, - name: step.name ?? step.action, - })), - output: template.spec.output ?? {}, - metadata: { name: template.metadata?.name }, - }; + } as TaskSpecV1beta3); } else { throw new InputError( `Unsupported apiVersion field in schema entity, ${ @@ -235,11 +266,12 @@ export async function createRouter( ); } - const result = await taskBroker.dispatch(taskSpec, { - ...req.body.secrets, - backstageToken: token, - // This is deprecated, but we need to support it for now if people are running their own task broker. - token: token, + const result = await taskBroker.dispatch({ + spec: taskSpec, + secrets: { + ...req.body.secrets, + backstageToken: token, + }, }); res.status(201).json({ id: result.taskId }); diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index fb161f6a4a..6d292edd1f 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-common +## 0.2.1 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/catalog-model@0.10.1 + - @backstage/types@0.1.3 + +## 0.2.0 + +### Minor Changes + +- 5e585bbc7f: **BREAKING**: Removed the `templateEntityV1beta3Schema` export + +### Patch Changes + +- e72d371296: Added `TemplateEntityV1beta2` which was moved here from + `@backstage/plugin-scaffolder-common`. It has also been marked as deprecated in + the process - please consider [migrating to `v1beta3` + templates](https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3). +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/catalog-model@0.10.0 + - @backstage/types@0.1.2 + ## 0.1.3 ### Patch Changes diff --git a/plugins/scaffolder-common/api-report.md b/plugins/scaffolder-common/api-report.md index 3bca8e74ed..1872aa3ed8 100644 --- a/plugins/scaffolder-common/api-report.md +++ b/plugins/scaffolder-common/api-report.md @@ -5,19 +5,19 @@ ```ts import { Entity } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; -import { JSONSchema } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/types'; +import { KindValidator } from '@backstage/catalog-model'; // @public export type TaskSpec = TaskSpecV1beta2 | TaskSpecV1beta3; -// @public +// @public @deprecated export interface TaskSpecV1beta2 { // (undocumented) apiVersion: 'backstage.io/v1beta2'; - // (undocumented) + // @deprecated (undocumented) baseUrl?: string; - // (undocumented) + // @deprecated (undocumented) metadata?: TemplateMetadata; // (undocumented) output: { @@ -26,6 +26,8 @@ export interface TaskSpecV1beta2 { // (undocumented) steps: TaskStep[]; // (undocumented) + templateInfo?: TemplateInfo; + // (undocumented) values: JsonObject; } @@ -33,9 +35,9 @@ export interface TaskSpecV1beta2 { export interface TaskSpecV1beta3 { // (undocumented) apiVersion: 'scaffolder.backstage.io/v1beta3'; - // (undocumented) + // @deprecated (undocumented) baseUrl?: string; - // (undocumented) + // @deprecated (undocumented) metadata?: TemplateMetadata; // (undocumented) output: { @@ -45,6 +47,8 @@ export interface TaskSpecV1beta3 { parameters: JsonObject; // (undocumented) steps: TaskStep[]; + // (undocumented) + templateInfo?: TemplateInfo; } // @public @@ -61,7 +65,34 @@ export interface TaskStep { name: string; } -// @public (undocumented) +// @public @deprecated +export interface TemplateEntityV1beta2 extends Entity { + // (undocumented) + apiVersion: 'backstage.io/v1beta2'; + // (undocumented) + kind: 'Template'; + // (undocumented) + spec: { + type: string; + parameters?: JsonObject | JsonObject[]; + steps: Array<{ + id?: string; + name?: string; + action: string; + input?: JsonObject; + if?: string | boolean; + }>; + output?: { + [name: string]: string; + }; + owner?: string; + }; +} + +// @public @deprecated +export const templateEntityV1beta2Validator: KindValidator; + +// @public export interface TemplateEntityV1beta3 extends Entity { // (undocumented) apiVersion: 'scaffolder.backstage.io/v1beta3'; @@ -85,10 +116,16 @@ export interface TemplateEntityV1beta3 extends Entity { }; } -// @public (undocumented) -export const templateEntityV1beta3Schema: JSONSchema; +// @public +export const templateEntityV1beta3Validator: KindValidator; // @public +export type TemplateInfo = { + entityRef: string; + baseUrl?: string; +}; + +// @public @deprecated export type TemplateMetadata = { name: string; }; diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 6b03a7c884..024241b60b 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "0.1.3", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -12,6 +12,9 @@ "module": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -25,21 +28,21 @@ "dist" ], "scripts": { - "build": "backstage-cli build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "bugs": { "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/types": "^0.1.1" + "@backstage/catalog-model": "^0.10.0", + "@backstage/types": "^0.1.2" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" } } diff --git a/plugins/scaffolder-common/src/TaskSpec.ts b/plugins/scaffolder-common/src/TaskSpec.ts index 8d8ccedbad..2c7eb26d5b 100644 --- a/plugins/scaffolder-common/src/TaskSpec.ts +++ b/plugins/scaffolder-common/src/TaskSpec.ts @@ -17,16 +17,29 @@ import { JsonValue, JsonObject } from '@backstage/types'; /** - * TemplateMetadata + * Metadata about the Template that was the originator of a scaffolder task, as + * stored in the database. * * @public + * @deprecated use templateInfo on the spec instead */ export type TemplateMetadata = { name: string; }; /** - * TaskStep + * Information about a template that is stored on a task specification. + * Includes a stringified entityRef, and the baseUrl which is usually the relative path of the template definition + * + * @public + */ +export type TemplateInfo = { + entityRef: string; + baseUrl?: string; +}; + +/** + * An individual step of a scaffolder task, as stored in the database. * * @public */ @@ -39,35 +52,45 @@ export interface TaskStep { } /** - * TaskSpecV1beta2 + * A scaffolder task as stored in the database, generated from a v1beta2 + * apiVersion Template. * * @public + * @deprecated Please convert your templates to TaskSpecV1beta3 on apiVersion + * scaffolder.backstage.io/v1beta3 */ export interface TaskSpecV1beta2 { apiVersion: 'backstage.io/v1beta2'; + /** @deprecated use templateInfo.baseUrl instead */ baseUrl?: string; values: JsonObject; steps: TaskStep[]; output: { [name: string]: string }; + /** @deprecated use templateInfo instead */ metadata?: TemplateMetadata; + templateInfo?: TemplateInfo; } /** - * TaskSpecV1beta3 + * A scaffolder task as stored in the database, generated from a v1beta3 + * apiVersion Template. * * @public */ export interface TaskSpecV1beta3 { apiVersion: 'scaffolder.backstage.io/v1beta3'; + /** @deprecated use templateInfo.baseUrl instead */ baseUrl?: string; parameters: JsonObject; steps: TaskStep[]; output: { [name: string]: JsonValue }; + /** @deprecated use templateInfo instead */ metadata?: TemplateMetadata; + templateInfo?: TemplateInfo; } /** - * TaskSpec + * A scaffolder task as stored in the database, generated from a Template. * * @public */ diff --git a/packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json b/plugins/scaffolder-common/src/Template.v1beta2.schema.json similarity index 100% rename from packages/catalog-model/src/schema/kinds/Template.v1beta2.schema.json rename to plugins/scaffolder-common/src/Template.v1beta2.schema.json diff --git a/packages/catalog-model/src/kinds/TemplateEntityV1beta2.test.ts b/plugins/scaffolder-common/src/TemplateEntityV1beta2.test.ts similarity index 100% rename from packages/catalog-model/src/kinds/TemplateEntityV1beta2.test.ts rename to plugins/scaffolder-common/src/TemplateEntityV1beta2.test.ts diff --git a/packages/catalog-model/src/kinds/TemplateEntityV1beta2.ts b/plugins/scaffolder-common/src/TemplateEntityV1beta2.ts similarity index 58% rename from packages/catalog-model/src/kinds/TemplateEntityV1beta2.ts rename to plugins/scaffolder-common/src/TemplateEntityV1beta2.ts index f4c2dfb5bc..280caec52f 100644 --- a/packages/catalog-model/src/kinds/TemplateEntityV1beta2.ts +++ b/plugins/scaffolder-common/src/TemplateEntityV1beta2.ts @@ -14,15 +14,21 @@ * limitations under the License. */ +import { + Entity, + entityKindSchemaValidator, + KindValidator, +} from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; -import type { Entity } from '../entity/Entity'; -import schema from '../schema/kinds/Template.v1beta2.schema.json'; -import { ajvCompiledJsonSchemaValidator } from './util'; +import schema from './Template.v1beta2.schema.json'; /** - * Backstage catalog Template kind Entity. Templates are used by the Scaffolder plugin to create new Components. + * Backstage catalog Template kind Entity. Templates are used by the Scaffolder + * plugin to create new entities, such as Components. * * @public + * @deprecated Please convert your templates to TemplateEntityV1beta3 on + * apiVersion scaffolder.backstage.io/v1beta3 */ export interface TemplateEntityV1beta2 extends Entity { apiVersion: 'backstage.io/v1beta2'; @@ -42,10 +48,18 @@ export interface TemplateEntityV1beta2 extends Entity { }; } +const validator = entityKindSchemaValidator(schema); + /** - * {@link KindValidator} for {@link TemplateEntityV1beta2}. + * Entity data validator for {@link TemplateEntityV1beta2}. * * @public + * @deprecated Please convert your templates to TemplateEntityV1beta3 on + * apiVersion scaffolder.backstage.io/v1beta3 */ -export const templateEntityV1beta2Validator = - ajvCompiledJsonSchemaValidator(schema); +export const templateEntityV1beta2Validator: KindValidator = { + // TODO(freben): Emulate the old KindValidator until we fix that type + async check(data: Entity) { + return validator(data) === data; + }, +}; diff --git a/plugins/scaffolder-common/src/TemplateEntityV1beta3.ts b/plugins/scaffolder-common/src/TemplateEntityV1beta3.ts index 2aefa5fd6b..13b699de69 100644 --- a/plugins/scaffolder-common/src/TemplateEntityV1beta3.ts +++ b/plugins/scaffolder-common/src/TemplateEntityV1beta3.ts @@ -14,10 +14,20 @@ * limitations under the License. */ +import { + Entity, + entityKindSchemaValidator, + KindValidator, +} from '@backstage/catalog-model'; import { JsonObject } from '@backstage/types'; -import { Entity } from '@backstage/catalog-model'; +import schema from './Template.v1beta3.schema.json'; -/** @public */ +/** + * Backstage catalog Template kind Entity. Templates are used by the Scaffolder + * plugin to create new entities, such as Components. + * + * @public + */ export interface TemplateEntityV1beta3 extends Entity { apiVersion: 'scaffolder.backstage.io/v1beta3'; kind: 'Template'; @@ -35,3 +45,17 @@ export interface TemplateEntityV1beta3 extends Entity { owner?: string; }; } + +const validator = entityKindSchemaValidator(schema); + +/** + * Entity data validator for {@link TemplateEntityV1beta3}. + * + * @public + */ +export const templateEntityV1beta3Validator: KindValidator = { + // TODO(freben): Emulate the old KindValidator until we fix that type + async check(data: Entity) { + return validator(data) === data; + }, +}; diff --git a/plugins/scaffolder-common/src/index.ts b/plugins/scaffolder-common/src/index.ts index 1197f48fed..e74a5f988f 100644 --- a/plugins/scaffolder-common/src/index.ts +++ b/plugins/scaffolder-common/src/index.ts @@ -20,15 +20,8 @@ * @packageDocumentation */ -import { JSONSchema } from '@backstage/catalog-model'; -import v1beta3Schema from './Template.v1beta3.schema.json'; - -export type { TemplateEntityV1beta3 } from './TemplateEntityV1beta3'; - -/** @public */ -export const templateEntityV1beta3Schema: JSONSchema = v1beta3Schema as Omit< - JSONSchema, - 'examples' ->; - export * from './TaskSpec'; +export { templateEntityV1beta2Validator } from './TemplateEntityV1beta2'; +export type { TemplateEntityV1beta2 } from './TemplateEntityV1beta2'; +export { templateEntityV1beta3Validator } from './TemplateEntityV1beta3'; +export type { TemplateEntityV1beta3 } from './TemplateEntityV1beta3'; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index dd7674a21b..ba618272b5 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder +## 0.12.3 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- e72d371296: Use `TemplateEntityV1beta2` from `@backstage/plugin-scaffolder-common` instead + of `@backstage/catalog-model`. +- Updated dependencies + - @backstage/plugin-scaffolder-common@0.2.0 + - @backstage/catalog-client@0.7.0 + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/plugin-permission-react@0.3.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + - @backstage/plugin-catalog-common@0.1.3 + ## 0.12.2 ### Patch Changes diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index f8ae64cd82..0a9145c780 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -27,7 +27,7 @@ import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; // Warning: (ae-missing-release-tag) "createScaffolderFieldExtension" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 0e31d6c4a5..827e8126f7 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "0.12.2", + "version": "0.12.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,30 +24,30 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-permission-react": "^0.3.0", - "@backstage/plugin-scaffolder-common": "^0.1.3", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-permission-react": "^0.3.1", + "@backstage/plugin-scaffolder-common": "^0.2.0", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -69,11 +72,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 601844780d..6b0de28ea9 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -16,7 +16,8 @@ import React, { ComponentType } from 'react'; import { Routes, Route, useOutlet } from 'react-router'; -import { TemplateEntityV1beta2, Entity } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 116b7ed82a..ec5d1272ab 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -23,7 +23,8 @@ import { Page, SupportButton, } from '@backstage/core-components'; -import { TemplateEntityV1beta2, Entity } from '@backstage/catalog-model'; +import { Entity } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { useRouteRef } from '@backstage/core-plugin-api'; import { EntityKindPicker, diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx index 2f49f40643..a642660bac 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { parseEntityRef } from '@backstage/catalog-model'; import { Content, ErrorPage, @@ -291,8 +292,9 @@ export const TaskPage = ({ loadingText }: TaskPageProps) => { const { output } = taskStream; const handleStartOver = () => { - if (!taskStream.task || !taskStream.task?.spec.metadata?.name) { + if (!taskStream.task || !taskStream.task?.spec.templateInfo?.entityRef) { navigate(generatePath(rootLink())); + return; } const formData = @@ -300,13 +302,17 @@ export const TaskPage = ({ loadingText }: TaskPageProps) => { ? taskStream.task!.spec.values : taskStream.task!.spec.parameters; + const { name } = parseEntityRef( + taskStream.task!.spec.templateInfo?.entityRef, + ); + navigate( generatePath( `${rootLink()}/templates/:templateName?${qs.stringify({ formData: JSON.stringify(formData), })}`, { - templateName: taskStream.task!.spec.metadata!.name, + templateName: name, }, ), ); diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index a02e6d3b14..3495409dd6 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -13,11 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Entity, - RELATION_OWNED_BY, - TemplateEntityV1beta2, -} from '@backstage/catalog-model'; +import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { ScmIntegrationIcon, scmIntegrationsApiRef, @@ -123,7 +120,8 @@ const DeprecationWarning = () => { const Title = ( - This template syntax is deprecated. Click for more info. + This template uses a syntax that has been deprecated, and should be + migrated to a newer syntax. Click for more info. ); @@ -131,7 +129,7 @@ const DeprecationWarning = () => {
diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx b/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx index 2ac0def547..a7f0b49132 100644 --- a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx +++ b/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx @@ -15,11 +15,8 @@ */ import React, { ComponentType } from 'react'; -import { - Entity, - stringifyEntityRef, - TemplateEntityV1beta2, -} from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/plugin-scaffolder-common'; import { Content, ContentHeader, @@ -90,6 +87,7 @@ export const TemplateList = ({ ))} diff --git a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx index c70f251eac..aa6630d4aa 100644 --- a/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx +++ b/plugins/scaffolder/src/components/TemplateTypePicker/TemplateTypePicker.test.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import { capitalize } from 'lodash'; -import { CatalogApi } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { TemplateTypePicker } from './TemplateTypePicker'; import { @@ -28,6 +27,7 @@ import { import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; import { ApiProvider } from '@backstage/core-app-api'; import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils'; +import { GetEntityFacetsResponse } from '@backstage/catalog-client'; const entities: Entity[] = [ { @@ -66,10 +66,15 @@ const apis = TestApiRegistry.from( [ catalogApiRef, { - getEntities: jest - .fn() - .mockImplementation(() => Promise.resolve({ items: entities })), - } as unknown as CatalogApi, + getEntityFacets: jest.fn().mockResolvedValue({ + facets: { + 'spec.type': entities.map(e => ({ + value: (e.spec as any).type, + count: 1, + })), + }, + } as GetEntityFacetsResponse), + }, ], [ alertApiRef, diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index 3dc609a63b..82f12ac0a3 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -46,7 +46,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(async () => ({ items: entities })), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx index b0577acfeb..bf566bd616 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx @@ -16,7 +16,7 @@ import React, { useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import useEffectOnce from 'react-use/lib/useEffectOnce'; -import { CatalogEntitiesRequest } from '@backstage/catalog-client'; +import { GetEntitiesRequest } from '@backstage/catalog-client'; import { Entity, makeValidator } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; @@ -40,7 +40,7 @@ export const EntityTagsPicker = ({ const kinds = uiSchema['ui:options']?.kinds as string[]; const { loading, value: existingTags } = useAsync(async () => { - const tagsRequest: CatalogEntitiesRequest = { fields: ['metadata.tags'] }; + const tagsRequest: GetEntitiesRequest = { fields: ['metadata.tags'] }; if (kinds) { tagsRequest.filter = { kind: kinds }; } diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index 31992fbc8a..b78d3add9e 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -43,7 +43,7 @@ describe('', () => { getEntityByName: jest.fn(), getEntities: jest.fn(async () => ({ items: entities })), addLocation: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), removeEntityByUid: jest.fn(), } as any; let Wrapper: React.ComponentType; diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 5dc394be6c..b68824932e 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 0.0.10 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/config@0.1.15 + - @backstage/search-common@0.2.4 + +## 0.0.9 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 4c0332e55c: chore(deps-dev): bump `@elastic/elasticsearch-mock` from 0.3.0 to 1.0.0 +- Updated dependencies + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + ## 0.0.8 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 6b21d0d0ab..80ad13f010 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "0.0.8", + "version": "0.0.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,18 +10,21 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^0.1.13", - "@backstage/search-common": "^0.2.2", + "@backstage/config": "^0.1.14", + "@backstage/search-common": "^0.2.3", "@elastic/elasticsearch": "7.13.0", "@acuris/aws-es-connection": "^2.2.0", "aws-sdk": "^2.948.0", @@ -30,9 +33,9 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.10.7-next.0", - "@backstage/cli": "^0.13.2-next.0", - "@elastic/elasticsearch-mock": "^0.3.0" + "@backstage/backend-common": "^0.10.8", + "@backstage/cli": "^0.14.0", + "@elastic/elasticsearch-mock": "^1.0.0" }, "files": [ "dist", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index c0b1f6778d..7fc2ef348a 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-search-backend-module-pg +## 0.2.8 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/search-common@0.2.4 + - @backstage/plugin-search-backend-node@0.4.7 + +## 0.2.7 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/search-common@0.2.3 + - @backstage/plugin-search-backend-node@0.4.6 + ## 0.2.6 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 392b9af73a..69b586129d 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.2.6", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,25 +10,28 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/search-common": "^0.2.2", - "@backstage/plugin-search-backend-node": "^0.4.5", + "@backstage/backend-common": "^0.10.8", + "@backstage/search-common": "^0.2.3", + "@backstage/plugin-search-backend-node": "^0.4.6", "lodash": "^4.17.21", "knex": "^1.0.2" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/cli": "^0.13.2" + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/cli": "^0.14.0" }, "files": [ "dist", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 6f664c086c..864376a7e7 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-backend-node +## 0.4.7 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/search-common@0.2.4 + +## 0.4.6 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/search-common@0.2.3 + ## 0.4.5 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index e2d83d0f4f..32403656c1 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "0.4.5", + "version": "0.4.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,24 +10,27 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "node-library" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/search-common": "^0.2.2", + "@backstage/search-common": "^0.2.3", "winston": "^3.2.1", "lunr": "^2.3.9", "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.10.7-next.0", - "@backstage/cli": "^0.13.2-next.0" + "@backstage/backend-common": "^0.10.8", + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 218615c66b..a3d40f7fc1 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-search-backend +## 0.4.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/search-common@0.2.4 + - @backstage/types@0.1.3 + - @backstage/plugin-auth-node@0.1.2 + - @backstage/plugin-permission-common@0.5.1 + - @backstage/plugin-permission-node@0.5.1 + - @backstage/plugin-search-backend-node@0.4.7 + +## 0.4.3 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/plugin-auth-node@0.1.1 + - @backstage/plugin-permission-common@0.5.0 + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + - @backstage/types@0.1.2 + - @backstage/plugin-permission-node@0.5.0 + - @backstage/plugin-search-backend-node@0.4.6 + ## 0.4.2 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 117e484c62..47651d6bc2 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "0.4.2", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,25 +10,28 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/search-common": "^0.2.2", - "@backstage/plugin-auth-node": "^0.1.0", - "@backstage/plugin-permission-common": "^0.4.0-next.0", - "@backstage/plugin-permission-node": "^0.4.3", - "@backstage/plugin-search-backend-node": "^0.4.5", - "@backstage/types": "^0.1.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/search-common": "^0.2.3", + "@backstage/plugin-auth-node": "^0.1.1", + "@backstage/plugin-permission-common": "^0.5.0", + "@backstage/plugin-permission-node": "^0.5.0", + "@backstage/plugin-search-backend-node": "^0.4.6", + "@backstage/types": "^0.1.2", "@types/express": "^4.17.6", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -40,7 +43,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index bb4877b6da..f9ec6f8687 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-search +## 0.7.0 + +### Minor Changes + +- f986369b2a: **BREAKING**: `useSearch` doesn't return anymore `open` and `toggleModal`. + The two properties have been moved to the `useSearchModal` hook. + + ``` + import { SearchModal, useSearchModal } from '@backstage/plugin-search'; + + const Foo = () => { + const { state, setOpen, toggleModal } = useSearchModal(); + + return ( + + ); + }; + ``` + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + ## 0.6.2 ### Patch Changes diff --git a/plugins/search/api-report.md b/plugins/search/api-report.md index a45f02564f..10ce787a6c 100644 --- a/plugins/search/api-report.md +++ b/plugins/search/api-report.md @@ -145,9 +145,17 @@ export const SearchContextProvider: ({ initialState, children, }: React_2.PropsWithChildren<{ - initialState?: SettableSearchContext | undefined; + initialState?: SearchContextState | undefined; }>) => JSX.Element; +// @public +export type SearchContextState = { + term: string; + types: string[]; + filters: JsonObject; + pageCursor?: string; +}; + // Warning: (ae-missing-release-tag) "SearchFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -201,6 +209,7 @@ export type SearchFilterWrapperProps = SearchFilterComponentProps & { // @public (undocumented) export const SearchModal: ({ open, + hidden, toggleModal, }: SearchModalProps) => JSX.Element; @@ -208,9 +217,8 @@ export const SearchModal: ({ // // @public (undocumented) export interface SearchModalProps { - // (undocumented) + hidden?: boolean; open?: boolean; - // (undocumented) toggleModal: () => void; } @@ -320,7 +328,13 @@ export type SidebarSearchProps = { // @public (undocumented) export const useSearch: () => SearchContextValue; -// Warnings were encountered during analysis: -// -// src/components/SearchContext/SearchContext.d.ts:23:5 - (ae-forgotten-export) The symbol "SettableSearchContext" needs to be exported by the entry point index.d.ts +// @public +export function useSearchModal(initialState?: boolean): { + state: { + hidden: boolean; + open: boolean; + }; + toggleModal: () => void; + setOpen: (open: boolean) => void; +}; ``` diff --git a/plugins/search/package.json b/plugins/search/package.json index 34baf41306..95104127bd 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "0.6.2", + "version": "0.7.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -20,25 +23,25 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/search-common": "^0.2.2", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/search-common": "^0.2.3", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,10 +56,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/search/src/components/LegacySearchPage/LegacySearchResult.tsx b/plugins/search/src/components/LegacySearchPage/LegacySearchResult.tsx index f48ffb61d7..ba92dba710 100644 --- a/plugins/search/src/components/LegacySearchPage/LegacySearchResult.tsx +++ b/plugins/search/src/components/LegacySearchPage/LegacySearchResult.tsx @@ -20,7 +20,7 @@ import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { Filters, FiltersButton, FiltersState } from './Filters'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { EmptyState, @@ -156,7 +156,7 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => { : undefined, url: `/catalog/${ entity.metadata.namespace?.toLocaleLowerCase('en-US') || - ENTITY_DEFAULT_NAMESPACE + DEFAULT_NAMESPACE }/${entity.kind.toLocaleLowerCase('en-US')}/${entity.metadata.name}`, })); }, []); diff --git a/plugins/search/src/components/SearchBar/SearchBar.tsx b/plugins/search/src/components/SearchBar/SearchBar.tsx index 2ddec22294..a203d27c93 100644 --- a/plugins/search/src/components/SearchBar/SearchBar.tsx +++ b/plugins/search/src/components/SearchBar/SearchBar.tsx @@ -169,13 +169,16 @@ export type SearchBarProps = Partial; export const SearchBar = ({ onChange, ...props }: SearchBarProps) => { const { term, setTerm } = useSearch(); - const handleChange = (newValue: string) => { - if (onChange) { - onChange(newValue); - } else { - setTerm(newValue); - } - }; + const handleChange = useCallback( + (newValue: string) => { + if (onChange) { + onChange(newValue); + } else { + setTerm(newValue); + } + }, + [onChange, setTerm], + ); return ; }; diff --git a/plugins/search/src/components/SearchContext/SearchContext.tsx b/plugins/search/src/components/SearchContext/SearchContext.tsx index 336041bf1f..a9f42fe5ca 100644 --- a/plugins/search/src/components/SearchContext/SearchContext.tsx +++ b/plugins/search/src/components/SearchContext/SearchContext.tsx @@ -31,45 +31,41 @@ import { searchApiRef } from '../../apis'; type SearchContextValue = { result: AsyncState; - term: string; setTerm: React.Dispatch>; - types: string[]; setTypes: React.Dispatch>; - filters: JsonObject; setFilters: React.Dispatch>; - open?: boolean; - toggleModal: () => void; - pageCursor?: string; setPageCursor: React.Dispatch>; fetchNextPage?: React.DispatchWithoutAction; fetchPreviousPage?: React.DispatchWithoutAction; -}; +} & SearchContextState; -type SettableSearchContext = Omit< - SearchContextValue, - | 'result' - | 'setTerm' - | 'setTypes' - | 'setFilters' - | 'toggleModal' - | 'setPageCursor' - | 'fetchNextPage' - | 'fetchPreviousPage' ->; +/** + * The initial state of `SearchContextProvider`. + * + * @public + */ +export type SearchContextState = { + term: string; + types: string[]; + filters: JsonObject; + pageCursor?: string; +}; export const SearchContext = createContext( undefined, ); +const searchInitialState: SearchContextState = { + term: '', + pageCursor: undefined, + filters: {}, + types: [], +}; + export const SearchContextProvider = ({ - initialState = { - term: '', - pageCursor: undefined, - filters: {}, - types: [], - }, + initialState = searchInitialState, children, -}: PropsWithChildren<{ initialState?: SettableSearchContext }>) => { +}: PropsWithChildren<{ initialState?: SearchContextState }>) => { const searchApi = useApi(searchApiRef); const [pageCursor, setPageCursor] = useState( initialState.pageCursor, @@ -77,11 +73,6 @@ export const SearchContextProvider = ({ const [filters, setFilters] = useState(initialState.filters); const [term, setTerm] = useState(initialState.term); const [types, setTypes] = useState(initialState.types); - const [open, setOpen] = useState(false); - const toggleModal = useCallback( - (): void => setOpen(prevState => !prevState), - [], - ); const prevTerm = usePrevious(term); @@ -90,7 +81,7 @@ export const SearchContextProvider = ({ searchApi.query({ term, filters, - pageCursor: pageCursor, + pageCursor, types, }), [term, filters, types, pageCursor], @@ -118,8 +109,6 @@ export const SearchContextProvider = ({ result, filters, setFilters, - open, - toggleModal, term, setTerm, types, diff --git a/plugins/search/src/components/SearchContext/SearchContextForStorybook.stories.tsx b/plugins/search/src/components/SearchContext/SearchContextForStorybook.stories.tsx index e969e0d8cc..36d670a1ed 100644 --- a/plugins/search/src/components/SearchContext/SearchContextForStorybook.stories.tsx +++ b/plugins/search/src/components/SearchContext/SearchContextForStorybook.stories.tsx @@ -16,7 +16,7 @@ import { ApiProvider } from '@backstage/core-app-api'; import { SearchResultSet } from '@backstage/search-common'; import { TestApiRegistry } from '@backstage/test-utils'; -import React, { ComponentProps } from 'react'; +import React, { ComponentProps, PropsWithChildren } from 'react'; import { searchApiRef } from '../../apis'; import { SearchContextProvider as RealSearchContextProvider } from './SearchContext'; @@ -33,13 +33,16 @@ type QueryResultProps = { export const SearchContextProvider = ( props: ComponentProps & QueryResultProps, ) => { - const { mockedResults, ...contextProps } = props; - const query: any = () => Promise.resolve(mockedResults || {}); - const apiRegistry = TestApiRegistry.from([searchApiRef, { query }]); - return ( - - - + + + ); }; + +export function SearchApiProvider(props: PropsWithChildren) { + const { mockedResults, children } = props; + const query: any = () => Promise.resolve(mockedResults || {}); + const apiRegistry = TestApiRegistry.from([searchApiRef, { query }]); + return ; +} diff --git a/plugins/search/src/components/SearchContext/index.tsx b/plugins/search/src/components/SearchContext/index.tsx index 682ade916f..8651e661c1 100644 --- a/plugins/search/src/components/SearchContext/index.tsx +++ b/plugins/search/src/components/SearchContext/index.tsx @@ -19,3 +19,5 @@ export { SearchContext, useSearch, } from './SearchContext'; + +export type { SearchContextState } from './SearchContext'; diff --git a/plugins/search/src/components/SearchModal/SearchModal.stories.tsx b/plugins/search/src/components/SearchModal/SearchModal.stories.tsx index e4b89000d5..aa0ad0479a 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.stories.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.stories.tsx @@ -18,9 +18,9 @@ import { wrapInTestApp } from '@backstage/test-utils'; import { Button } from '@material-ui/core'; import React, { ComponentType } from 'react'; import { rootRouteRef } from '../../plugin'; -import { useSearch } from '../SearchContext'; -import { SearchContextProvider } from '../SearchContext/SearchContextForStorybook.stories'; +import { SearchApiProvider } from '../SearchContext/SearchContextForStorybook.stories'; import { SearchModal } from './SearchModal'; +import { useSearchModal } from './useSearchModal'; const mockResults = { results: [ @@ -57,23 +57,23 @@ export default { decorators: [ (Story: ComponentType<{}>) => wrapInTestApp( - + - , + , { mountedRoutes: { '/search': rootRouteRef } }, ), ], }; export const Default = () => { - const { open, toggleModal } = useSearch(); + const { state, toggleModal } = useSearchModal(); return ( <> - + ); }; diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index b59be710de..d3b2a825e2 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -24,7 +24,6 @@ import { rootRouteRef } from '../../plugin'; import { searchApiRef } from '../../apis'; import { SearchModal } from './SearchModal'; -import { SearchContextProvider } from '../SearchContext'; describe('SearchModal', () => { const query = jest.fn().mockResolvedValue({ results: [] }); @@ -34,14 +33,16 @@ describe('SearchModal', () => { [searchApiRef, { query }], ); + beforeEach(() => { + query.mockClear(); + }); + const toggleModal = jest.fn(); it('Should render the Modal correctly', async () => { await renderInTestApp( - - - + , { mountedRoutes: { @@ -51,14 +52,13 @@ describe('SearchModal', () => { ); expect(screen.getByRole('dialog')).toBeInTheDocument(); + expect(query).toHaveBeenCalledTimes(1); }); it('Calls toggleModal handler', async () => { await renderInTestApp( - - - + , { mountedRoutes: { @@ -66,7 +66,25 @@ describe('SearchModal', () => { }, }, ); + + expect(query).toHaveBeenCalledTimes(1); userEvent.keyboard('{esc}'); expect(toggleModal).toHaveBeenCalledTimes(1); }); + + it('should render SearchModal hiding its content', async () => { + const { getByTestId } = await renderInTestApp( + + , + { + mountedRoutes: { + '/search': rootRouteRef, + }, + }, + ); + + expect(getByTestId('search-bar-next')).toBeInTheDocument(); + expect(getByTestId('search-bar-next')).not.toBeVisible(); + }); }); diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx index 1f0a879f96..2a71e53ea8 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.tsx @@ -38,7 +38,21 @@ import { Link, useContent } from '@backstage/core-components'; import { rootRouteRef } from '../../plugin'; export interface SearchModalProps { + /** + * If true, it renders the modal. + */ open?: boolean; + /** + * This is supposed to be used together with the open prop. + * If `hidden` is true, it hides the modal. + * If `open` is false, the value of `hidden` has no effect on the modal. + * Use `open` for controlling whether the modal should be rendered or not. + */ + hidden?: boolean; + /** + * a function invoked when a search item is pressed or when the dialog + * should be closed. + */ toggleModal: () => void; } @@ -57,7 +71,7 @@ const useStyles = makeStyles(theme => ({ viewResultsLink: { verticalAlign: '0.5em' }, })); -export const Modal = ({ open = true, toggleModal }: SearchModalProps) => { +export const Modal = ({ toggleModal }: SearchModalProps) => { const getSearchLink = useRouteRef(rootRouteRef); const classes = useStyles(); @@ -75,16 +89,7 @@ export const Modal = ({ open = true, toggleModal }: SearchModalProps) => { }; return ( - + <> @@ -139,14 +144,34 @@ export const Modal = ({ open = true, toggleModal }: SearchModalProps) => { - + ); }; -export const SearchModal = ({ open = true, toggleModal }: SearchModalProps) => { +export const SearchModal = ({ + open = true, + hidden, + toggleModal, +}: SearchModalProps) => { + const classes = useStyles(); + return ( - - - + ); }; diff --git a/plugins/search/src/components/SearchModal/index.tsx b/plugins/search/src/components/SearchModal/index.tsx index ec0053951d..646dff0a62 100644 --- a/plugins/search/src/components/SearchModal/index.tsx +++ b/plugins/search/src/components/SearchModal/index.tsx @@ -15,3 +15,4 @@ */ export { SearchModal } from './SearchModal'; export type { SearchModalProps } from './SearchModal'; +export { useSearchModal } from './useSearchModal'; diff --git a/plugins/search/src/components/SearchModal/useSearchModal.test.tsx b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx new file mode 100644 index 0000000000..424dffff76 --- /dev/null +++ b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx @@ -0,0 +1,73 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { act, renderHook } from '@testing-library/react-hooks'; +import { useSearchModal } from './useSearchModal'; + +describe('useSearchModal', () => { + it.each([ + [true, { open: true, hidden: false }], + [false, { open: false, hidden: true }], + ])( + 'should return the correct state when initial state is %s', + (initialState, result) => { + const rendered = renderHook(() => useSearchModal(initialState)); + + expect(rendered.result.current.state).toEqual(result); + }, + ); + + it('should keep open forever to true once modal is toggled', () => { + const rendered = renderHook(() => useSearchModal()); + act(() => rendered.result.current.toggleModal()); + + expect(rendered.result.current.state).toEqual({ + open: true, + hidden: false, + }); + + act(() => rendered.result.current.toggleModal()); + expect(rendered.result.current.state).toEqual({ + open: true, + hidden: true, + }); + }); + + it('should keep open to false if setOpen(false) is invoked on an initially closed modal', () => { + const rendered = renderHook(() => useSearchModal()); + act(() => rendered.result.current.setOpen(false)); + expect(rendered.result.current.state).toEqual({ + open: false, + hidden: true, + }); + }); + + it('should keep open forever to true even when the modal transition from opened to closed', () => { + const rendered = renderHook(() => useSearchModal()); + + act(() => rendered.result.current.setOpen(true)); + expect(rendered.result.current.state).toEqual({ + open: true, + hidden: false, + }); + + act(() => rendered.result.current.setOpen(false)); + expect(rendered.result.current.state).toEqual({ + open: true, + hidden: true, + }); + }); +}); diff --git a/plugins/search/src/components/SearchModal/useSearchModal.tsx b/plugins/search/src/components/SearchModal/useSearchModal.tsx new file mode 100644 index 0000000000..3871687d1a --- /dev/null +++ b/plugins/search/src/components/SearchModal/useSearchModal.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2022 The Backstage Authors + * + * 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 { useCallback, useState } from 'react'; + +/** + * Use this hook to manage the state of {@link SearchModal} + * and change its visibility. + * + * @public + * + * @param initialState - pass `true` to make the modal initially visible + * @returns an object containing the state of the modal together with + * functions for changing the visibility of the modal. + */ +export function useSearchModal(initialState = false) { + const [state, setState] = useState({ + hidden: !initialState, + open: initialState, + }); + + const toggleModal = useCallback( + () => + setState(prevState => ({ + open: true, + hidden: !prevState.hidden, + })), + [], + ); + + const setOpen = useCallback( + (open: boolean) => + setState(prevState => ({ + open: prevState.open || open, + hidden: !open, + })), + [], + ); + + return { state, toggleModal, setOpen }; +} diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx index 6b4171a024..1aae64c463 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx @@ -33,7 +33,6 @@ describe('SearchType.Accordion', () => { term: '', types: [], filters: {}, - toggleModal: jest.fn(), setTerm: jest.fn(), setTypes: jest.fn(), setFilters: jest.fn(), diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx index 54f09023bc..741ee6e83f 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.test.tsx @@ -33,7 +33,6 @@ describe('SearchType.Tabs', () => { term: '', types: [], filters: {}, - toggleModal: jest.fn(), setTerm: jest.fn(), setTypes: jest.fn(), setFilters: jest.fn(), diff --git a/plugins/search/src/components/SidebarSearchModal/SidebarSearchModal.tsx b/plugins/search/src/components/SidebarSearchModal/SidebarSearchModal.tsx index b8f20de67d..bbf4eef4e4 100644 --- a/plugins/search/src/components/SidebarSearchModal/SidebarSearchModal.tsx +++ b/plugins/search/src/components/SidebarSearchModal/SidebarSearchModal.tsx @@ -17,15 +17,14 @@ import React from 'react'; import SearchIcon from '@material-ui/icons/Search'; import { SidebarItem } from '@backstage/core-components'; import { IconComponent } from '@backstage/core-plugin-api'; -import { SearchModal } from '../SearchModal'; -import { useSearch } from '../SearchContext'; +import { SearchModal, useSearchModal } from '../SearchModal'; export type SidebarSearchModalProps = { icon?: IconComponent; }; export const SidebarSearchModal = (props: SidebarSearchModalProps) => { - const { open, toggleModal } = useSearch(); + const { state, toggleModal } = useSearchModal(); const Icon = props.icon ? props.icon : SearchIcon; return ( @@ -36,7 +35,7 @@ export const SidebarSearchModal = (props: SidebarSearchModalProps) => { text="Search" onClick={toggleModal} /> - + ); }; diff --git a/plugins/search/src/index.ts b/plugins/search/src/index.ts index 99c3f5177b..cef0355fb4 100644 --- a/plugins/search/src/index.ts +++ b/plugins/search/src/index.ts @@ -32,13 +32,14 @@ export type { SearchBarProps, } from './components/SearchBar'; export { SearchContextProvider, useSearch } from './components/SearchContext'; +export type { SearchContextState } from './components/SearchContext'; export { SearchFilter, SearchFilterNext } from './components/SearchFilter'; export type { SearchAutocompleteFilterProps, SearchFilterComponentProps, SearchFilterWrapperProps, } from './components/SearchFilter'; -export { SearchModal } from './components/SearchModal'; +export { SearchModal, useSearchModal } from './components/SearchModal'; export type { SearchModalProps } from './components/SearchModal'; export { SearchPage as Router } from './components/SearchPage'; export { SearchResultPager } from './components/SearchResultPager'; diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 5f87df9a3a..5b907793c7 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-sentry +## 0.3.37 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.3.36 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 48137dc5e1..056dab64b0 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.3.36", + "version": "0.3.37", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,21 +25,21 @@ "sentry" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +52,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 11bc03104a..e34ba20bf8 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-shortcuts +## 0.2.0 + +### Minor Changes + +- dc9fd0acf9: Use Avatar instead of custom icon for ShortcutIcon + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + ## 0.1.22 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index d3bcb14f15..2627c26825 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.1.22", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,21 +10,24 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/shortcuts/src/ShortcutIcon.tsx b/plugins/shortcuts/src/ShortcutIcon.tsx index 94a894fcb0..be78928452 100644 --- a/plugins/shortcuts/src/ShortcutIcon.tsx +++ b/plugins/shortcuts/src/ShortcutIcon.tsx @@ -15,33 +15,28 @@ */ import React from 'react'; +import { makeStyles } from '@material-ui/core/styles'; +import Avatar from '@material-ui/core/Avatar'; type Props = { text: string; color: string; }; -export const ShortcutIcon = ({ text, color }: Props) => { - const size = 28; - return ( - - - - {text} - - - ); +const useStyles = makeStyles(theme => ({ + avatar: (props: Props) => ({ + color: theme.palette.getContrastText(props.color), + backgroundColor: props.color, + width: 28, + height: 28, + fontWeight: 'bold', + fontSize: 13, + filter: 'contrast(150%) brightness(1.4)', + }), +})); + +export const ShortcutIcon = (props: Props) => { + const classes = useStyles(props); + + return {props.text}; }; diff --git a/plugins/shortcuts/src/ShortcutItem.test.tsx b/plugins/shortcuts/src/ShortcutItem.test.tsx index e080026f00..528eb13efa 100644 --- a/plugins/shortcuts/src/ShortcutItem.test.tsx +++ b/plugins/shortcuts/src/ShortcutItem.test.tsx @@ -24,7 +24,6 @@ import { renderInTestApp, wrapInTestApp, } from '@backstage/test-utils'; -import { pageTheme } from '@backstage/theme'; import { SidebarContext } from '@backstage/core-components'; describe('ShortcutItem', () => { @@ -77,27 +76,4 @@ describe('ShortcutItem', () => { expect(screen.getByText('MT')).toBeInTheDocument(); }); }); - - it('gets the color based on the theme', async () => { - const { rerender } = await renderInTestApp( - , - ); - - expect(document.querySelector('circle')?.getAttribute('fill')).toEqual( - pageTheme.tool.colors[0], - ); - - const newShortcut: Shortcut = { - id: 'id', - url: '/catalog', - title: 'some title', - }; - rerender(wrapInTestApp()); - - await waitFor(() => { - expect(document.querySelector('circle')?.getAttribute('fill')).toEqual( - pageTheme.home.colors[0], - ); - }); - }); }); diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index c0de393aab..57ee474d67 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-sonarqube +## 0.2.17 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.16 ### Patch Changes diff --git a/plugins/sonarqube/api-report.md b/plugins/sonarqube/api-report.md index b23ed65ddd..a7549a689c 100644 --- a/plugins/sonarqube/api-report.md +++ b/plugins/sonarqube/api-report.md @@ -16,7 +16,6 @@ export const EntitySonarQubeCard: ({ variant, duplicationRatings, }: { - entity?: Entity | undefined; variant?: InfoCardVariants | undefined; duplicationRatings?: | { @@ -38,7 +37,6 @@ export const SonarQubeCard: ({ variant, duplicationRatings, }: { - entity?: Entity | undefined; variant?: InfoCardVariants | undefined; duplicationRatings?: DuplicationRating[] | undefined; }) => JSX.Element; @@ -52,5 +50,5 @@ export { sonarQubePlugin }; // Warnings were encountered during analysis: // -// src/components/SonarQubeCard/SonarQubeCard.d.ts:11:5 - (ae-forgotten-export) The symbol "DuplicationRating" needs to be exported by the entry point index.d.ts +// src/components/SonarQubeCard/SonarQubeCard.d.ts:9:5 - (ae-forgotten-export) The symbol "DuplicationRating" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index fb2de64ffe..f32f2c252c 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.2.16", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -23,21 +26,21 @@ "sonarcloud" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +53,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx index ca3ddbda76..4527c2a3e3 100644 --- a/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx +++ b/plugins/sonarqube/src/components/SonarQubeCard/SonarQubeCard.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { Entity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import { Chip, Grid } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; @@ -90,7 +89,6 @@ export const SonarQubeCard = ({ variant = 'gridItem', duplicationRatings = defaultDuplicationRatings, }: { - entity?: Entity; variant?: InfoCardVariants; duplicationRatings?: DuplicationRating[]; }) => { diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index badc0f06fc..75bd177266 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-splunk-on-call +## 0.3.23 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.3.22 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 1bc8948d95..81dee187b7 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.3.22", + "version": "0.3.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,21 +24,21 @@ "splunk-on-call" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 3128854594..b53beb79a4 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.10 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/plugin-tech-insights-common@0.2.3 + - @backstage/plugin-tech-insights-node@0.2.4 + +## 0.1.9 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/errors@0.2.1 + - @backstage/config@0.1.14 + - @backstage/plugin-tech-insights-common@0.2.2 + - @backstage/plugin-tech-insights-node@0.2.3 + ## 0.1.8 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index fc2c6b7add..ef9a15c261 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.8", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin-module" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,20 @@ "scorecard" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-tech-insights-common": "^0.2.1", - "@backstage/plugin-tech-insights-node": "^0.2.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-tech-insights-common": "^0.2.2", + "@backstage/plugin-tech-insights-node": "^0.2.3", "ajv": "^7.0.3", "json-rules-engine": "^6.1.2", "lodash": "^4.17.21", @@ -43,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/node-cron": "^3.0.1" }, "files": [ diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 36e7aa97a1..906e142cfa 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-tech-insights-backend +## 0.2.6 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/plugin-tech-insights-common@0.2.3 + - @backstage/plugin-tech-insights-node@0.2.4 + +## 0.2.5 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 538ca90790: Use updated type names from `@backstage/catalog-client` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/plugin-tech-insights-common@0.2.2 + - @backstage/plugin-tech-insights-node@0.2.3 + ## 0.2.4 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 5a60e478d8..eec4379f9d 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.2.4", + "version": "0.2.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,22 +25,22 @@ "reporting" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-tech-insights-common": "^0.2.1", - "@backstage/plugin-tech-insights-node": "^0.2.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-tech-insights-common": "^0.2.2", + "@backstage/plugin-tech-insights-node": "^0.2.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -51,8 +54,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.17", - "@backstage/cli": "^0.13.2", + "@backstage/backend-test-utils": "^0.1.18", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "@types/node-cron": "^3.0.0", "@types/semver": "^7.3.8", diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts index b99f6a1c02..a51ce0ab83 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityMetadataFactRetriever.test.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { PluginEndpointDiscovery, getVoidLogger, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { CatalogListResponse } from '@backstage/catalog-client'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; import { entityMetadataFactRetriever } from './entityMetadataFactRetriever'; const getEntitiesMock = jest.fn(); @@ -36,7 +36,7 @@ const discovery: jest.Mocked = { getExternalBaseUrl: jest.fn(), }; -const defaultEntityListResponse: CatalogListResponse = { +const defaultEntityListResponse: GetEntitiesResponse = { items: [ { apiVersion: 'backstage.io/v1beta1', diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts index ea0801f17c..2108379f06 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/entityOwnershipFactRetriever.test.ts @@ -15,13 +15,13 @@ */ import { entityOwnershipFactRetriever } from './entityOwnershipFactRetriever'; -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { PluginEndpointDiscovery, getVoidLogger, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { CatalogListResponse } from '@backstage/catalog-client'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; const getEntitiesMock = jest.fn(); jest.mock('@backstage/catalog-client', () => { @@ -36,7 +36,7 @@ const discovery: jest.Mocked = { getExternalBaseUrl: jest.fn(), }; -const defaultEntityListResponse: CatalogListResponse = { +const defaultEntityListResponse: GetEntitiesResponse = { items: [ { apiVersion: 'backstage.io/v1beta1', diff --git a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts index 6ed9b12523..a3604129b7 100644 --- a/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/factRetrievers/techdocsFactRetriever.test.ts @@ -15,13 +15,13 @@ */ import { techdocsFactRetriever } from './techdocsFactRetriever'; -import { Entity, RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { PluginEndpointDiscovery, getVoidLogger, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { CatalogListResponse } from '@backstage/catalog-client'; +import { GetEntitiesResponse } from '@backstage/catalog-client'; const getEntitiesMock = jest.fn(); jest.mock('@backstage/catalog-client', () => { @@ -36,7 +36,7 @@ const discovery: jest.Mocked = { getExternalBaseUrl: jest.fn(), }; -const defaultEntityListResponse: CatalogListResponse = { +const defaultEntityListResponse: GetEntitiesResponse = { items: [ { apiVersion: 'backstage.io/v1beta1', diff --git a/plugins/tech-insights-common/CHANGELOG.md b/plugins/tech-insights-common/CHANGELOG.md index 947c22756f..e895a82e6c 100644 --- a/plugins/tech-insights-common/CHANGELOG.md +++ b/plugins/tech-insights-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights-common +## 0.2.3 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/types@0.1.3 + +## 0.2.2 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/types@0.1.2 + ## 0.2.1 ### Patch Changes diff --git a/plugins/tech-insights-common/package.json b/plugins/tech-insights-common/package.json index a0b840da74..648306ae33 100644 --- a/plugins/tech-insights-common/package.json +++ b/plugins/tech-insights-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-common", - "version": "0.2.1", + "version": "0.2.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "common-library" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,20 +25,20 @@ ], "scripts": { "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { "@types/luxon": "^2.0.5", "luxon": "^2.0.2", - "@backstage/types": "^0.1.1" + "@backstage/types": "^0.1.2" }, "devDependencies": { - "@backstage/cli": "^0.13.2-next.0" + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index c38c36ecd9..836743c773 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-tech-insights-node +## 0.2.4 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/config@0.1.15 + - @backstage/plugin-tech-insights-common@0.2.3 + +## 0.2.3 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/config@0.1.14 + - @backstage/plugin-tech-insights-common@0.2.2 + ## 0.2.2 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 05c6f10071..1170d0fc79 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.2.2", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,24 +24,24 @@ "tech-insights" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/config": "^0.1.13", - "@backstage/plugin-tech-insights-common": "^0.2.1", + "@backstage/backend-common": "^0.10.8", + "@backstage/config": "^0.1.14", + "@backstage/plugin-tech-insights-common": "^0.2.2", "@types/luxon": "^2.0.5", "luxon": "^2.0.2", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2" + "@backstage/cli": "^0.14.0" }, "files": [ "dist" diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index af16d5f347..e442fb5192 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-tech-insights +## 0.1.9 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + - @backstage/types@0.1.2 + - @backstage/plugin-tech-insights-common@0.2.2 + ## 0.1.8 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index b7b1b6877c..23281edf9c 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.1.8", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -9,25 +9,28 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-tech-insights-common": "^0.2.1", - "@backstage/theme": "^0.2.14", - "@backstage/types": "^0.1.1", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-tech-insights-common": "^0.2.2", + "@backstage/theme": "^0.2.15", + "@backstage/types": "^0.1.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index bafe2212cf..c74f524f9a 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-tech-radar +## 0.5.6 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.5.5 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 29601d1755..c61f0007a8 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.5.5", + "version": "0.5.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,19 +24,19 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean", - "start": "backstage-cli plugin:serve" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -46,10 +49,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index b05e8a6dad..8fe30e06c5 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-techdocs-backend +## 0.13.5 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + - @backstage/search-common@0.2.4 + - @backstage/techdocs-common@0.11.9 + - @backstage/plugin-catalog-common@0.1.4 + +## 0.13.4 + +### Patch Changes + +- 453145abba: Do not use cross-fetch in the backend +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 811c710a21: Fix bug where tech docs collator stores search indices with wrong entity ref casing. Make the collator to conform legacyPathCasing configuration option. +- 7aeb491394: Replace use of deprecated `ENTITY_DEFAULT_NAMESPACE` constant with `DEFAULT_NAMESPACE`. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/search-common@0.2.3 + - @backstage/techdocs-common@0.11.8 + - @backstage/plugin-catalog-common@0.1.3 + ## 0.13.3 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 0beabaf719..0087512e8e 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "0.13.3", + "version": "0.13.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,26 +25,25 @@ "techdocs" ], "scripts": { - "start": "backstage-cli backend:dev", - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/plugin-catalog-common": "^0.1.2", - "@backstage/search-common": "^0.2.2", - "@backstage/techdocs-common": "^0.11.7", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/plugin-catalog-common": "^0.1.3", + "@backstage/search-common": "^0.2.3", + "@backstage/techdocs-common": "^0.11.8", "@types/express": "^4.17.6", - "cross-fetch": "^3.1.5", "dockerode": "^3.3.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -53,8 +55,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/test-utils": "^0.2.5", "@types/dockerode": "^3.3.0", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 66eb52c1aa..05e9c0ce52 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -15,7 +15,7 @@ */ import { Entity, - ENTITY_DEFAULT_NAMESPACE, + DEFAULT_NAMESPACE, stringifyEntityRef, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; @@ -111,8 +111,7 @@ export class DocsBuilder { try { storedEtag = ( await this.publisher.fetchTechDocsMetadata({ - namespace: - this.entity.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE, + namespace: this.entity.metadata.namespace ?? DEFAULT_NAMESPACE, kind: this.entity.kind, name: this.entity.metadata.name, }) diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts index 7e7545ea1f..e81fc1e7a9 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts @@ -198,8 +198,8 @@ describe('DefaultTechDocsCollator', () => { componentType: entity!.spec!.type, lifecycle: entity!.spec!.lifecycle, owner: '', - kind: entity.kind, - name: entity.metadata.name, + kind: entity.kind.toLocaleLowerCase('en-US'), + name: entity.metadata.name.toLocaleLowerCase('en-US'), authorization: { resourceRef: `component:default/${entity.metadata.name}`, }, diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts index 5149fe6c09..987e8c6b15 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts @@ -145,9 +145,7 @@ export class DefaultTechDocsCollator implements DocumentCollator { path: doc.location, }), path: doc.location, - kind: entity.kind, - namespace: entity.metadata.namespace || 'default', - name: entity.metadata.name, + ...entityInfo, entityTitle: entity.metadata.title, componentType: entity.spec?.type?.toString() || 'other', lifecycle: (entity.spec?.lifecycle as string) || '', diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts index 1eb8c8f56f..1830dbfcf0 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts @@ -31,7 +31,7 @@ import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer'; jest.mock('../DocsBuilder'); -jest.mock('cross-fetch', () => ({ +jest.mock('node-fetch', () => ({ __esModule: true, default: async () => { return { diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 4d407ab54a..2979d2efe4 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -15,7 +15,7 @@ */ import { PluginEndpointDiscovery } from '@backstage/backend-common'; -import { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model'; +import { Entity, DEFAULT_NAMESPACE } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { assertError, NotFoundError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -24,7 +24,7 @@ import { PreparerBuilder, PublisherBase, } from '@backstage/techdocs-common'; -import fetch from 'cross-fetch'; +import fetch from 'node-fetch'; import { PassThrough } from 'stream'; import * as winston from 'winston'; import { TechDocsCache } from '../cache'; @@ -177,7 +177,7 @@ export class DocsSynchronizer { // Fetch techdocs_metadata.json from the publisher and from cache. const baseUrl = await discovery.getBaseUrl('techdocs'); - const namespace = entity.metadata?.namespace || ENTITY_DEFAULT_NAMESPACE; + const namespace = entity.metadata?.namespace || DEFAULT_NAMESPACE; const kind = entity.kind; const name = entity.metadata.name; const legacyPathCasing = diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 3ff8c0e175..ae4f121cc8 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-techdocs +## 0.13.4 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 6553985cd4: Match text size of admonitions to main content text size. +- 9df7b43e1a: Improve overall appearance of highlighted code in docs. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/integration-react@0.1.22 + - @backstage/plugin-catalog@0.8.0 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/plugin-search@0.7.0 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + - @backstage/theme@0.2.15 + ## 0.13.3 ### Patch Changes diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index 9a25cb6375..9459e616a1 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -169,9 +169,7 @@ export const EntityListDocsTable: { // Warning: (ae-missing-release-tag) "EntityTechdocsContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const EntityTechdocsContent: (_props: { - entity?: Entity | undefined; -}) => JSX.Element; +export const EntityTechdocsContent: (_props: {}) => JSX.Element; // Warning: (ae-missing-release-tag) "isTechDocsAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -395,5 +393,5 @@ export class TechDocsStorageClient implements TechDocsStorageApi { // // src/home/components/EntityListDocsTable.d.ts:11:5 - (ae-forgotten-export) The symbol "columnFactories" needs to be exported by the entry point index.d.ts // src/home/components/EntityListDocsTable.d.ts:12:5 - (ae-forgotten-export) The symbol "actionFactories" needs to be exported by the entry point index.d.ts -// src/plugin.d.ts:29:5 - (ae-forgotten-export) The symbol "TabsConfig" needs to be exported by the entry point index.d.ts +// src/plugin.d.ts:27:5 - (ae-forgotten-export) The symbol "TabsConfig" needs to be exported by the entry point index.d.ts ``` diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 794e386136..cfe9f04b6a 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "0.13.3", + "version": "0.13.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -22,27 +25,27 @@ "techdocs" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", - "@backstage/integration-react": "^0.1.21", - "@backstage/plugin-catalog": "^0.7.12", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/plugin-search": "^0.6.2", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", + "@backstage/integration-react": "^0.1.22", + "@backstage/plugin-catalog": "^0.8.0", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/plugin-search": "^0.7.0", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -62,10 +65,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/techdocs/src/Router.tsx b/plugins/techdocs/src/Router.tsx index 102cda979a..0ba69c021f 100644 --- a/plugins/techdocs/src/Router.tsx +++ b/plugins/techdocs/src/Router.tsx @@ -40,10 +40,7 @@ export const Router = () => { ); }; -type Props = { - /** @deprecated The entity is now grabbed from context instead */ - entity?: Entity; -}; +type Props = {}; export const EmbeddedDocsRouter = (_props: Props) => { const { entity } = useEntity(); diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 7869fc1b9b..c12b17b486 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -142,6 +142,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { const techdocsSanitizer = useApi(configApiRef); const { namespace = '', kind = '', name = '' } = entityRef; const { state, path, content: rawPage } = useTechDocsReader(); + const isDarkTheme = theme.palette.type === 'dark'; const [sidebars, setSidebars] = useState(); const [dom, setDom] = useState(null); @@ -219,6 +220,27 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { --md-accent-fg-color: ${theme.palette.primary.main}; --md-default-fg-color--lightest: ${theme.palette.textVerySubtle}; } + .codehilite .gd, .highlight .gd { + background-color: ${isDarkTheme ? 'rgba(248,81,73,0.65)' : '#fdd'}; + } + .codehilite .gi, .highlight .gi { + background-color: ${isDarkTheme ? 'rgba(46,160,67,0.65)' : '#dfd'}; + } + .highlight .kd { + color: ${isDarkTheme ? '#4aaaf7' : '#3b78e7'}; + } + .highlight .k { + color: ${isDarkTheme ? '#4aaaf7' : '#3b78e7'}; + } + .highlight .nx { + color: ${isDarkTheme ? '#ff53a3' : '#ec407a'}; + } + .highlight .s1 { + color: ${isDarkTheme ? '#1cad46' : 'rgb(13, 144, 79)'}; + } + .highlight .kt { + color: ${isDarkTheme ? '#4aaaf7' : '#3e61a2'}; + } .md-main__inner { margin-top: 0; } .md-sidebar { position: fixed; bottom: 100px; width: 20rem; } .md-sidebar--secondary { right: 2rem; } @@ -248,7 +270,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { } .md-typeset table:not([class]) th { font-weight: bold; } .md-typeset .admonition, .md-typeset details { - font-size: 1rem; + font-size: inherit; } /* style the checkmarks of the task list */ @@ -351,21 +373,22 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => { }), ]), [ + techdocsSanitizer, + techdocsStorageApi, kind, name, namespace, scmIntegrationsApi, - techdocsStorageApi, - techdocsSanitizer, - theme.palette.action.disabledBackground, - theme.palette.background.default, - theme.palette.background.paper, - theme.palette.primary.main, - theme.palette.success.main, - theme.palette.text.primary, - theme.palette.textSubtle, - theme.palette.textVerySubtle, theme.typography.fontFamily, + theme.palette.text.primary, + theme.palette.primary.main, + theme.palette.background.paper, + theme.palette.background.default, + theme.palette.textVerySubtle, + theme.palette.textSubtle, + theme.palette.action.disabledBackground, + theme.palette.success.main, + isDarkTheme, isPinned, ], ); diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index a5cb799a70..5e508db080 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-todo-backend +## 0.1.23 + +### Patch Changes + +- Fix for the previous release with missing type declarations. +- Updated dependencies + - @backstage/backend-common@0.10.9 + - @backstage/catalog-client@0.7.1 + - @backstage/catalog-model@0.10.1 + - @backstage/config@0.1.15 + - @backstage/errors@0.2.2 + - @backstage/integration@0.7.4 + +## 0.1.22 + +### Patch Changes + +- c77c5c7eb6: Added `backstage.role` to `package.json` +- edbc03814a: Replace usage of `serializeEntityRef` with `stringifyEntityRef` +- deaf6065db: Adapt to the new `CatalogApi.getLocationByRef` +- 216725b434: Updated to use new names for `parseLocationRef` and `stringifyLocationRef` +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/backend-common@0.10.8 + - @backstage/catalog-client@0.7.0 + - @backstage/errors@0.2.1 + - @backstage/integration@0.7.3 + - @backstage/catalog-model@0.10.0 + - @backstage/config@0.1.14 + ## 0.1.21 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 3371dbbecc..0cfc768e96 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.21", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.cjs.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "backend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -17,20 +20,21 @@ "directory": "plugins/todo-backend" }, "scripts": { - "build": "backstage-cli backend:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.10.7", - "@backstage/catalog-client": "^0.6.0", - "@backstage/catalog-model": "^0.9.10", - "@backstage/config": "^0.1.13", - "@backstage/errors": "^0.2.0", - "@backstage/integration": "^0.7.2", + "@backstage/backend-common": "^0.10.8", + "@backstage/catalog-client": "^0.7.0", + "@backstage/catalog-model": "^0.10.0", + "@backstage/config": "^0.1.14", + "@backstage/errors": "^0.2.1", + "@backstage/integration": "^0.7.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -39,7 +43,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", + "@backstage/cli": "^0.14.0", "@types/supertest": "^2.0.8", "msw": "^0.35.0", "supertest": "^6.1.3" diff --git a/plugins/todo-backend/src/service/TodoReaderService.test.ts b/plugins/todo-backend/src/service/TodoReaderService.test.ts index 3d86a1726b..985687c6bb 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.test.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.test.ts @@ -45,13 +45,13 @@ function mockCatalogClient(entity?: Entity): jest.Mocked { addLocation: jest.fn(), getEntities: jest.fn(), getEntityByName: jest.fn(), - getOriginLocationByEntity: jest.fn(), - getLocationByEntity: jest.fn(), + getLocationByRef: jest.fn(), getLocationById: jest.fn(), removeLocationById: jest.fn(), removeEntityByUid: jest.fn(), refreshEntity: jest.fn(), getEntityAncestors: jest.fn(), + getEntityFacets: jest.fn(), }; if (entity) { mock.getEntityByName.mockReturnValue(entity); @@ -301,7 +301,7 @@ describe('TodoReaderService', () => { await expect(service.listTodos({ entity: entityName })).rejects.toEqual( expect.objectContaining({ name: 'NotFoundError', - message: 'Entity not found, Component:default/my-component', + message: 'Entity not found, component:default/my-component', }), ); expect(catalogClient.getEntityByName).toHaveBeenCalledWith(entityName, { @@ -321,7 +321,7 @@ describe('TodoReaderService', () => { expect.objectContaining({ name: 'InputError', message: - 'No entity location annotation found for Component:my-component', + 'No entity location annotation found for component:default/my-component', }), ); }); @@ -342,7 +342,7 @@ describe('TodoReaderService', () => { await expect(service.listTodos({ entity: entityName })).rejects.toEqual( expect.objectContaining({ name: 'InputError', - message: `Invalid entity location type for Component:my-component, got 'file'`, + message: `Invalid entity location type for component:default/my-component, got 'file'`, }), ); }); @@ -363,7 +363,7 @@ describe('TodoReaderService', () => { await expect(service.listTodos({ entity: entityName })).rejects.toEqual( expect.objectContaining({ name: 'InputError', - message: `Invalid entity source location type for Component:my-component, got 'file'`, + message: `Invalid entity source location type for component:default/my-component, got 'file'`, }), ); }); diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts index 54957d89c4..86f53057da 100644 --- a/plugins/todo-backend/src/service/TodoReaderService.ts +++ b/plugins/todo-backend/src/service/TodoReaderService.ts @@ -17,11 +17,11 @@ import { InputError, NotFoundError } from '@backstage/errors'; import { CatalogApi } from '@backstage/catalog-client'; import { - LOCATION_ANNOTATION, - SOURCE_LOCATION_ANNOTATION, - serializeEntityRef, + ANNOTATION_LOCATION, + ANNOTATION_SOURCE_LOCATION, Entity, - parseLocationReference, + parseLocationRef, + stringifyEntityRef, } from '@backstage/catalog-model'; import { TodoReader } from '../lib'; import { ListTodosRequest, ListTodosResponse, TodoService } from './types'; @@ -71,7 +71,7 @@ export class TodoReaderService implements TodoService { }); if (!entity) { throw new NotFoundError( - `Entity not found, ${serializeEntityRef(req.entity)}`, + `Entity not found, ${stringifyEntityRef(req.entity)}`, ); } @@ -128,12 +128,12 @@ export class TodoReaderService implements TodoService { private getEntitySourceUrl(entity: Entity) { const sourceLocation = - entity.metadata.annotations?.[SOURCE_LOCATION_ANNOTATION]; + entity.metadata.annotations?.[ANNOTATION_SOURCE_LOCATION]; if (sourceLocation) { - const parsed = parseLocationReference(sourceLocation); + const parsed = parseLocationRef(sourceLocation); if (parsed.type !== 'url') { throw new InputError( - `Invalid entity source location type for ${serializeEntityRef( + `Invalid entity source location type for ${stringifyEntityRef( entity, )}, got '${parsed.type}'`, ); @@ -141,12 +141,12 @@ export class TodoReaderService implements TodoService { return parsed.target; } - const location = entity.metadata.annotations?.[LOCATION_ANNOTATION]; + const location = entity.metadata.annotations?.[ANNOTATION_LOCATION]; if (location) { - const parsed = parseLocationReference(location); + const parsed = parseLocationRef(location); if (parsed.type !== 'url') { throw new InputError( - `Invalid entity location type for ${serializeEntityRef( + `Invalid entity location type for ${stringifyEntityRef( entity, )}, got '${parsed.type}'`, ); @@ -154,7 +154,7 @@ export class TodoReaderService implements TodoService { return parsed.target; } throw new InputError( - `No entity location annotation found for ${serializeEntityRef(entity)}`, + `No entity location annotation found for ${stringifyEntityRef(entity)}`, ); } } diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index bec930df20..4dc29b7559 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-todo +## 0.2.1 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 27eccab216: Replaces use of deprecated catalog-model constants. +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/plugin-catalog-react@0.6.15 + - @backstage/catalog-model@0.10.0 + - @backstage/theme@0.2.15 + ## 0.2.0 ### Minor Changes diff --git a/plugins/todo/dev/index.tsx b/plugins/todo/dev/index.tsx index fe547812ec..375c89e4a4 100644 --- a/plugins/todo/dev/index.tsx +++ b/plugins/todo/dev/index.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Entity, LOCATION_ANNOTATION } from '@backstage/catalog-model'; +import { Entity, ANNOTATION_LOCATION } from '@backstage/catalog-model'; import { createDevApp } from '@backstage/dev-utils'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import OnlineIcon from '@material-ui/icons/Cloud'; @@ -31,7 +31,7 @@ const entity: Entity = { metadata: { name: 'backstage', annotations: { - [LOCATION_ANNOTATION]: + [ANNOTATION_LOCATION]: 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', }, }, diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 8282772d90..cd593bbd40 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.0", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,6 +10,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -17,22 +20,22 @@ "directory": "plugins/todo" }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.10", - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/plugin-catalog-react": "^0.6.14", - "@backstage/theme": "^0.2.14", + "@backstage/catalog-model": "^0.10.0", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/plugin-catalog-react": "^0.6.15", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -42,10 +45,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 423e978352..fa42d325e7 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-user-settings +## 0.3.20 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- 12dd25c2a1: Updated example code for registering feature flags in the `EmptyFlags` component +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/theme@0.2.15 + ## 0.3.19 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 4c33a1ac50..d934b17487 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.3.19", + "version": "0.3.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,6 +11,9 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "homepage": "https://backstage.io", "repository": { "type": "git", @@ -21,19 +24,19 @@ "backstage" ], "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -44,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx b/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx index 785f398d6f..0e2b911978 100644 --- a/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx +++ b/plugins/user-settings/src/components/FeatureFlags/EmptyFlags.tsx @@ -22,9 +22,7 @@ const EXAMPLE = `import { createPlugin } from '@backstage/core-plugin-api'; export default createPlugin({ id: 'plugin-name', - register({ router, featureFlags }) { - featureFlags.register('enable-example-feature'); - }, + featureFlags: [{ name: 'enable-example-feature' }], }); `; diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index bcfbf2b88b..1c2188ccf7 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-xcmetrics +## 0.2.19 + +### Patch Changes + +- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 +- c77c5c7eb6: Added `backstage.role` to `package.json` +- Updated dependencies + - @backstage/core-components@0.8.9 + - @backstage/core-plugin-api@0.6.1 + - @backstage/errors@0.2.1 + - @backstage/theme@0.2.15 + ## 0.2.18 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index b765a1be2d..8fec920ccb 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.18", + "version": "0.2.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -10,21 +10,24 @@ "main": "dist/index.esm.js", "types": "dist/index.d.ts" }, + "backstage": { + "role": "frontend-plugin" + }, "scripts": { - "build": "backstage-cli plugin:build", - "start": "backstage-cli plugin:serve", - "lint": "backstage-cli lint", - "test": "backstage-cli test", + "build": "backstage-cli package build", + "start": "backstage-cli package start", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean" + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.8.8", - "@backstage/core-plugin-api": "^0.6.0", - "@backstage/errors": "^0.2.0", - "@backstage/theme": "^0.2.14", + "@backstage/core-components": "^0.8.9", + "@backstage/core-plugin-api": "^0.6.1", + "@backstage/errors": "^0.2.1", + "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -37,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.13.2", - "@backstage/core-app-api": "^0.5.2", - "@backstage/dev-utils": "^0.2.21", - "@backstage/test-utils": "^0.2.4", + "@backstage/cli": "^0.14.0", + "@backstage/core-app-api": "^0.5.3", + "@backstage/dev-utils": "^0.2.22", + "@backstage/test-utils": "^0.2.5", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 2958b5b719..22d00e5dfe 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -219,10 +219,12 @@ const NO_WARNING_PACKAGES = [ 'packages/release-manifests', 'packages/version-bridge', 'plugins/auth-node', + 'plugins/catalog-backend-module-aws', 'plugins/catalog-backend-module-ldap', 'plugins/catalog-backend-module-msgraph', 'plugins/catalog-common', 'plugins/catalog-graph', + 'plugins/catalog-react', 'plugins/permission-backend', 'plugins/permission-common', 'plugins/permission-node', diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js index f25c6838fb..4b3891c5ce 100755 --- a/scripts/create-github-release.js +++ b/scripts/create-github-release.js @@ -63,7 +63,7 @@ const octokit = new Octokit({ }); // Get the message of the commit responsible for a tag -async function getCommitMessageUsingTagName(tagName) { +async function getCommitUsingTagName(tagName) { // Get the tag SHA using the provided tag name const refData = await octokit.git.getRef({ owner: GH_OWNER, @@ -114,39 +114,57 @@ async function getCommitMessageUsingTagName(tagName) { // Example Commit Message // Merge pull request #3555 from backstage/changeset-release/master Version Packages - return commitData.data.message; + return { sha: commitSha, message: commitData.data.message }; } // There is a PR number in our expected commit message. Get the description of that PR. -async function getReleaseDescriptionFromCommitMessage(commitMessage) { - // It should exactly match the pattern of changeset commit message, or else will abort. - const expectedMessage = RegExp(EXPECTED_COMMIT_MESSAGE); - if (!expectedMessage.test(commitMessage)) { - throw new Error( - `Expected regex did not match commit message: ${commitMessage}`, +async function getReleaseDescriptionFromCommit(commit) { + let pullRequestBody = undefined; + + const { data: pullRequests } = + await octokit.repos.listPullRequestsAssociatedWithCommit({ + owner: GH_OWNER, + repo: GH_REPO, + commit_sha: commit.sha, + }); + if (pullRequests.length === 1) { + pullRequestBody = pullRequests[0].body; + } else { + console.warn( + `Found ${pullRequests.length} pull requests for commit ${commit.sha}, falling back to parsing commit message`, ); + + // It should exactly match the pattern of changeset commit message, or else will abort. + const expectedMessage = RegExp(EXPECTED_COMMIT_MESSAGE); + if (!expectedMessage.test(commit.message)) { + throw new Error( + `Expected regex did not match commit message: ${commit.message}`, + ); + } + + // Get the PR description from the commit message + const prNumber = commit.message.match(expectedMessage).groups.prNumber; + console.log( + `Identified the changeset Pull request - https://github.com/backstage/backstage/pull/${prNumber}`, + ); + + const { data } = await octokit.pulls.get({ + owner: GH_OWNER, + repo: GH_REPO, + pull_number: prNumber, + }); + + pullRequestBody = data.body; } - // Get the PR description from the commit message - const prNumber = commitMessage.match(expectedMessage).groups.prNumber; - console.log( - `Identified the changeset Pull request - https://github.com/backstage/backstage/pull/${prNumber}`, - ); - - const { data } = await octokit.pulls.get({ - owner: GH_OWNER, - repo: GH_REPO, - pull_number: prNumber, - }); - // Use the PR description to prepare for the release description - const isChangesetRelease = commitMessage.includes(CHANGESET_RELEASE_BRANCH); + const isChangesetRelease = commit.message.includes(CHANGESET_RELEASE_BRANCH); if (isChangesetRelease) { - const lines = data.body.split('\n'); + const lines = pullRequestBody.split('\n'); return lines.slice(lines.indexOf('# Releases') + 1).join('\n'); } - return data.body; + return pullRequestBody; } // Create Release on GitHub. @@ -179,10 +197,8 @@ async function createRelease(releaseDescription) { } async function main() { - const commitMessage = await getCommitMessageUsingTagName(TAG_NAME); - const releaseDescription = await getReleaseDescriptionFromCommitMessage( - commitMessage, - ); + const commit = await getCommitUsingTagName(TAG_NAME); + const releaseDescription = await getReleaseDescriptionFromCommit(commit); await createRelease(releaseDescription); } diff --git a/scripts/migrate-location-types.js b/scripts/migrate-location-types.js deleted file mode 100755 index 168a5e825c..0000000000 --- a/scripts/migrate-location-types.js +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env node -/* - * Copyright 2020 The Backstage Authors - * - * 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. - */ - -// This is a script that helps you migrate any locations that are using -// deprecated location types. Change the below URL to point towards your -// catalog API endpoint and execute the script. It will delete and add -// back the locations with the correct type one by one. - -const BASE_URL = 'http://localhost:7007/api/catalog'; // Change me - -const deprecatedTypes = [ - 'github', - 'github/api', - 'bitbucket/api', - 'gitlab/api', - 'azure/api', -]; - -async function main() { - const locations = await request('GET', `${BASE_URL}/locations`); - - for (const { data: location } of locations) { - if (!deprecatedTypes.includes(location.type)) { - continue; - } - console.log(`${location.type} -> url : ${location.target}`); - await request('DELETE', `${BASE_URL}/locations/${location.id}`); - try { - await request('POST', `${BASE_URL}/locations`, { - type: 'url', - target: location.target, - }); - } catch (error) { - console.log(`Failed to add back location ${location.target}`); - throw error; - } - } -} - -async function request(method, url, body) { - return new Promise((resolve, reject) => { - const parsedUrl = require('url').parse(url); - - const req = require('http').request( - { - method, - ...parsedUrl, - headers: body - ? { - 'Content-Type': 'application/json', - } - : {}, - }, - res => { - const chunks = []; - res.on('data', chunk => { - chunks.push(chunk); - }); - - res.on('end', () => { - if (res.statusCode >= 300) { - reject( - new Error( - `${method} to ${url} failed with status ${res.statusCode}`, - ), - ); - return; - } - try { - const responseBody = Buffer.concat(chunks).toString('utf8').trim(); - if (responseBody) { - resolve(JSON.parse(responseBody)); - } else { - resolve(); - } - } catch (error) { - reject(error); - } - }); - }, - ); - - req.on('error', reject); - - if (body) { - req.write(JSON.stringify(body)); - } - - req.end(); - }); -} - -main().catch(error => { - console.error(error.stack); - process.exit(1); -}); diff --git a/storybook/package.json b/storybook/package.json index ea488e94ac..d4ef3861d7 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -15,13 +15,13 @@ "react-dom": "^17.0.2" }, "devDependencies": { - "@storybook/addon-a11y": "^6.4.18", - "@storybook/addon-actions": "^6.4.18", - "@storybook/addon-links": "^6.4.18", - "@storybook/addon-storysource": "^6.4.18", - "@storybook/addons": "^6.4.14", - "@storybook/react": "^6.4.18", - "storybook-dark-mode": "^1.0.8" + "@storybook/addon-a11y": "^6.4.19", + "@storybook/addon-actions": "^6.4.19", + "@storybook/addon-links": "^6.4.19", + "@storybook/addon-storysource": "^6.4.19", + "@storybook/addons": "^6.4.19", + "@storybook/react": "^6.4.19", + "storybook-dark-mode": "^1.0.9" }, "peerDependencies": { "@backstage/theme": "link:../packages/theme", diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 284ada1cb2..c53f5fe7be 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -1310,19 +1310,19 @@ resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9" integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA== -"@storybook/addon-a11y@^6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.18.tgz#c61f71cd7b17aff408835ee35e29bf4a0716ece7" - integrity sha512-sqsA5pXXKKDsquSXu5KC8WxQ1gg5ZoNIltWRgmJCEt4a0bkGUzn2iz+uW/gbt4NOVWGPXKvmMBLT/q4Q9gb+og== +"@storybook/addon-a11y@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.19.tgz#fb92840b5559b429afe2f28211440a5b5d1b6fcb" + integrity sha512-dG6easap6W4AqyggVZPq8lBrhza8StA8J4eYz/GVdoXINSGtq/casV0rkmY3+SUXhPYux5oGavHo86j5I4Q/0Q== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/api" "6.4.18" - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/components" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/api" "6.4.19" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/components" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.18" + "@storybook/theming" "6.4.19" axe-core "^4.2.0" core-js "^3.8.2" global "^4.4.0" @@ -1332,17 +1332,17 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-actions@^6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.18.tgz#e997060e1b0af62f9f831301a56a3addfc1f1365" - integrity sha512-qPw5qfbWPmyOdaXxAVAbdVLVVE31gRrkH0ESUps+FXVNypRz1/0lJ6M2VrtOHMrFbGBl94SALdqsHOx6OYZKwg== +"@storybook/addon-actions@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.19.tgz#10631d9c0a6669810264ea7fac3bff7201553084" + integrity sha512-GpSvP8xV8GfNkmtGJjfCgaOx6mbjtyTK0aT9FqX9pU0s+KVMmoCTrBh43b7dWrwxxas01yleBK9VpYggzhi/Fw== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/api" "6.4.18" - "@storybook/components" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/api" "6.4.19" + "@storybook/components" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.18" + "@storybook/theming" "6.4.19" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1356,16 +1356,16 @@ util-deprecate "^1.0.2" uuid-browser "^3.1.0" -"@storybook/addon-links@^6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.18.tgz#edb61db6c291056f7d3c64566aea436a6796c50a" - integrity sha512-yIbL57+tV1Ei2b7zTGU/T7muBFByTPm/8IN5SA5tSFYRTR9VtFuvBXco6I9Wz9GLN/REyVa4+AoDahokk7+vPQ== +"@storybook/addon-links@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.19.tgz#001f26c4ffc7d36fd6018b8a137449948b337869" + integrity sha512-ebFHYlGDQkHSmI5QEJb1NxGNToVOLgjKkxXUe+JXX7AfHvrWiXVrN/57aOtBPZzj4h2jRPRTZgwR5glhPIlfEQ== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.18" + "@storybook/router" "6.4.19" "@types/qs" "^6.9.5" core-js "^3.8.2" global "^4.4.0" @@ -1374,18 +1374,18 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addon-storysource@^6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.4.18.tgz#00f0fb919b6224bfa8379b7c4c66e0b32b443921" - integrity sha512-02hs9dnfJs5lihQ0c/Cv4+lQNmkR0Fd+isEL+oVNcWTE9g0LVSLzC3evzeQCJv0SDzei7T0N+G7pF1P2dmc5PQ== +"@storybook/addon-storysource@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/addon-storysource/-/addon-storysource-6.4.19.tgz#09ec47b0c9f68ba9590edfcc7bd72984c048d272" + integrity sha512-WcjPgd0/m9rGMQbf6H2/wvXUhW5lSELWdXeCCK1taQHQUjhs8tq83fa7OkI9kE25drPiUJuPzObbCoYr94hftQ== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/api" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/components" "6.4.18" - "@storybook/router" "6.4.18" - "@storybook/source-loader" "6.4.18" - "@storybook/theming" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/api" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/components" "6.4.19" + "@storybook/router" "6.4.19" + "@storybook/source-loader" "6.4.19" + "@storybook/theming" "6.4.19" core-js "^3.8.2" estraverse "^5.2.0" loader-utils "^2.0.0" @@ -1394,35 +1394,35 @@ react-syntax-highlighter "^13.5.3" regenerator-runtime "^0.13.7" -"@storybook/addons@6.4.18", "@storybook/addons@^6.4.14": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.18.tgz#fc92a4a608680f2e182a5e896ed382792f6b774e" - integrity sha512-fd3S79P4jJCYZNA2JxA1Xnkj0UlHGQ4Vg72aroWy4OQFlgGQor1LgPfM6RaJ9rh/4k4BXYPXsS7wzI0UWKG3Lw== +"@storybook/addons@6.4.19", "@storybook/addons@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.19.tgz#797d912b8b5a86cd6e0d31fa4c42d1f80808a432" + integrity sha512-QNyRYhpqmHV8oJxxTBdkRlLSbDFhpBvfvMfIrIT1UXb/eemdBZTaCGVvXZ9UixoEEI7f8VwAQ44IvkU5B1509w== dependencies: - "@storybook/api" "6.4.18" - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/api" "6.4.19" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.18" - "@storybook/theming" "6.4.18" + "@storybook/router" "6.4.19" + "@storybook/theming" "6.4.19" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" global "^4.4.0" regenerator-runtime "^0.13.7" -"@storybook/api@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/api/-/api-6.4.18.tgz#92da2b69aeec712419bec9bab5c8434ff1776e97" - integrity sha512-tSbsHKklBysuSmw4T+cKzMj6mQh/42m9F8+2iJns2XG/IUKpMAzFg/9dlgCTW+ay6dJwsR79JGIc9ccIe4SMgQ== +"@storybook/api@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/api/-/api-6.4.19.tgz#8000a0e4c52c39b910b4ccc6731419e8e71800ef" + integrity sha512-aDvea+NpQCBjpNp9YidO1Pr7fzzCp15FSdkG+2ihGQfv5raxrN+IIJnGUXecpe71nvlYiB+29UXBVK7AL0j51Q== dependencies: - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/router" "6.4.18" + "@storybook/router" "6.4.19" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.18" + "@storybook/theming" "6.4.19" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1434,10 +1434,10 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-webpack4@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.18.tgz#8bae72b9e982d35a5a9f2b7f9af9d85a9c2dc966" - integrity sha512-N/OGjTnc7CpVoDnfoI49uMjAIpGqh2lWHFYNIWaUoG1DNnTt1nCc49hw9awjFc5KgaYOwJmVg1SYYE8Afssu+Q== +"@storybook/builder-webpack4@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.19.tgz#ca8228639be06e50d5f1555b844dd4177e5068ad" + integrity sha512-wxA6SMH11duc9D53aeVVBwrVRemFIoxHp/dOugkkg6ZZFAb4ZmWzf/ENc3vQIZdZpfNRi7IZIZEOfoHc994cmw== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -1460,22 +1460,22 @@ "@babel/preset-env" "^7.12.11" "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" - "@storybook/addons" "6.4.18" - "@storybook/api" "6.4.18" - "@storybook/channel-postmessage" "6.4.18" - "@storybook/channels" "6.4.18" - "@storybook/client-api" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/components" "6.4.18" - "@storybook/core-common" "6.4.18" - "@storybook/core-events" "6.4.18" - "@storybook/node-logger" "6.4.18" - "@storybook/preview-web" "6.4.18" - "@storybook/router" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/api" "6.4.19" + "@storybook/channel-postmessage" "6.4.19" + "@storybook/channels" "6.4.19" + "@storybook/client-api" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/components" "6.4.19" + "@storybook/core-common" "6.4.19" + "@storybook/core-events" "6.4.19" + "@storybook/node-logger" "6.4.19" + "@storybook/preview-web" "6.4.19" + "@storybook/router" "6.4.19" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.18" - "@storybook/theming" "6.4.18" - "@storybook/ui" "6.4.18" + "@storybook/store" "6.4.19" + "@storybook/theming" "6.4.19" + "@storybook/ui" "6.4.19" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" autoprefixer "^9.8.6" @@ -1509,51 +1509,51 @@ webpack-hot-middleware "^2.25.1" webpack-virtual-modules "^0.2.2" -"@storybook/channel-postmessage@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.18.tgz#24547fe7cee599969fd62df22142ba7046099a8e" - integrity sha512-SKapUREPkqzKoBMpOJrZddE9PCR8CJkPTcDpjDqcRsTvToRWsux3pvzmuW4iGYnHNh+GQml7Rz9x85WfMIpfyQ== +"@storybook/channel-postmessage@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.19.tgz#5db4e1188aaa9de05fee3ba6a6b7f3b988cade03" + integrity sha512-E5h/itFzQ/6M08LR4kqlgqqmeO3tmavI+nUAlZrkCrotpJFNMHE2i0PQHg0TkFJrRDpYcrwD+AjUW4IwdqrisQ== dependencies: - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" core-js "^3.8.2" global "^4.4.0" qs "^6.10.0" telejson "^5.3.2" -"@storybook/channel-websocket@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.18.tgz#cf3a03e88b983c2953cb76a40a964806790567c4" - integrity sha512-ROqNZAFB1gP9u8dmlM4KxykXHsd1ifunBgFY3ncQKeRi2Oh30OMVB2ZhNdoIF8i8X5ZBwSpId1o6nQhL2e/EJA== +"@storybook/channel-websocket@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.19.tgz#5b2f34f9089966bab66c55721766d3d1803edf2e" + integrity sha512-cXKwQjIXttfdUyZlcHORelUmJ5nUKswsnCA/qy7IRWpZjD8yQJcNk1dYC+tTHDVqFgdRT89pL0hRRB1rlaaR8Q== dependencies: - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" core-js "^3.8.2" global "^4.4.0" telejson "^5.3.2" -"@storybook/channels@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.18.tgz#2907aca0039b5eb9ae305112f14c488c2621c2f6" - integrity sha512-Bh4l7VKKR2ImLbZ9XgL/DzT3lFv9+SLiCu1ozfpBZGHUCOLyHRnkG/h8wYvRkF9s3tpNwOtaCaqD1vkkZfr3uw== +"@storybook/channels@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.19.tgz#095bbaee494bf5b03f7cb92d34626f2f5063cb31" + integrity sha512-EwyoncFvTfmIlfsy8jTfayCxo2XchPkZk/9txipugWSmc057HdklMKPLOHWP0z5hLH0IbVIKXzdNISABm36jwQ== dependencies: core-js "^3.8.2" ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.18.tgz#61c7c90f3f099e4d3bcc36576d2adbe2e5ef6eee" - integrity sha512-ua2Q692Fz2b3q5M/Qzjixg2LArwrcHGBmht06bNw/jrRfyFeTUHOhh5BT7LxSEetUgHATH/Y1GW40xza9rXFNw== +"@storybook/client-api@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.19.tgz#131597e160f112f51240a4e407191053e5ed972f" + integrity sha512-OCrT5Um3FDvZnimQKwWtwsaI+5agPwq2i8YiqlofrI/NPMKp0I7DEkCGwE5IRD1Q8BIKqHcMo5tTmfYi0AxyOg== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/channel-postmessage" "6.4.18" - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/channel-postmessage" "6.4.19" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.18" + "@storybook/store" "6.4.19" "@types/qs" "^6.9.5" "@types/webpack-env" "^1.16.0" core-js "^3.8.2" @@ -1568,23 +1568,23 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.18.tgz#4ad8ea7d67b17e5db8f15cffcc2f984df3479462" - integrity sha512-ciBaASMaB2ZPksbuyDbp3++5SZxbhcihEpl+RQcAVV8g+TUyBZKIcHt8HNHicTczz5my1EydZovMh1IkSBMICA== +"@storybook/client-logger@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.19.tgz#b2011ad2fa446cce4a9afdb41974b2a576e9fad2" + integrity sha512-zmg/2wyc9W3uZrvxaW4BfHcr40J0v7AGslqYXk9H+ERLVwIvrR4NhxQFaS6uITjBENyRDxwzfU3Va634WcmdDQ== dependencies: core-js "^3.8.2" global "^4.4.0" -"@storybook/components@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/components/-/components-6.4.18.tgz#1f3eba9ab69a09b9468af0126d6e7ab040655ca4" - integrity sha512-LAPKYWgB6S10Vzt0IWa1Ihf9EAuQOGxlqehTuxYLOwMOKbto8iEbGRse/XaQfxdZf/RbmOL4u+7nVRROWgOEjg== +"@storybook/components@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/components/-/components-6.4.19.tgz#084ba21f26a3eeab82f45178de6899688eecb2fc" + integrity sha512-q/0V37YAJA7CNc+wSiiefeM9+3XVk8ixBNylY36QCGJgIeGQ5/79vPyUe6K4lLmsQwpmZsIq1s1Ad5+VbboeOA== dependencies: "@popperjs/core" "^2.6.0" - "@storybook/client-logger" "6.4.18" + "@storybook/client-logger" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/theming" "6.4.18" + "@storybook/theming" "6.4.19" "@types/color-convert" "^2.0.0" "@types/overlayscrollbars" "^1.12.0" "@types/react-syntax-highlighter" "11.0.5" @@ -1606,21 +1606,21 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/core-client@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.18.tgz#7f2feb961864dcf6de501a94a41900fd36b43657" - integrity sha512-F9CqW31Mr9Qde90uqPorpkiS+P7UteKYmdHlV0o0czeWaL+MEhpY+3pRJuRIIjX5C7Vc89TvljMqs37Khakmdg== +"@storybook/core-client@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.19.tgz#fc6902c4321ae9e7c2858126172bc0752a84321c" + integrity sha512-rQHRZjhArPleE7/S8ZUolgzwY+hC0smSKX/3PQxO2GcebDjnJj6+iSV3h+aSMHMmTdoCQvjYw9aBpT8scuRe+A== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/channel-postmessage" "6.4.18" - "@storybook/channel-websocket" "6.4.18" - "@storybook/client-api" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/channel-postmessage" "6.4.19" + "@storybook/channel-websocket" "6.4.19" + "@storybook/client-api" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/preview-web" "6.4.18" - "@storybook/store" "6.4.18" - "@storybook/ui" "6.4.18" + "@storybook/preview-web" "6.4.19" + "@storybook/store" "6.4.19" + "@storybook/ui" "6.4.19" airbnb-js-shims "^2.2.1" ansi-to-html "^0.6.11" core-js "^3.8.2" @@ -1632,10 +1632,10 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/core-common@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.18.tgz#0688a0a4a80cdbc161966c5a7ff49e755d64bbab" - integrity sha512-y4e43trNyQ3/v0Wpi240on7yVooUQvJBhJxOGEfcxAMRtcDa0ZCxHO4vAFX3k3voQOSmiXItXfJ1eGo/K+u0Fw== +"@storybook/core-common@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.19.tgz#18e6c6095ebd9a94b074529917c693084921d3ca" + integrity sha512-X1pJJkO48DFxl6iyEemIKqRkJ7j9/cBh3BRBUr+xZHXBvnD0GKDXIocwh0PjSxSC6XSu3UCQnqtKi3PbjRl8Dg== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -1658,7 +1658,7 @@ "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" "@babel/register" "^7.12.1" - "@storybook/node-logger" "6.4.18" + "@storybook/node-logger" "6.4.19" "@storybook/semver" "^7.3.2" "@types/node" "^14.0.10" "@types/pretty-hrtime" "^1.0.0" @@ -1687,29 +1687,29 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core-events@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.18.tgz#630a19425eb387c6134f29b967c30458c65f7ea8" - integrity sha512-lCT3l0rFs6CuVpD8+mwmj1lUTomGErySTxi0KmVd2AWQj8kJL90EfS0jHSU5JIXScDvuwXDXLLmvMfqNU+zHdg== +"@storybook/core-events@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.19.tgz#d2a03156783a3cb9bd9f7ba81a06a798a5c296ae" + integrity sha512-KICzUw6XVQUJzFSCXfvhfHAuyhn4Q5J4IZEfuZkcGJS4ODkrO6tmpdYE5Cfr+so95Nfp0ErWiLUuodBsW9/rtA== dependencies: core-js "^3.8.2" -"@storybook/core-server@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.18.tgz#520935f7f330a734488e733ad4cf15a9556679b5" - integrity sha512-7e2QUtD8/TE14P9X/xsBDMBbNVi/etTtMKKhsG2TG25daRz+6qadbM9tNP0YwvIDk452cNYJkjflV48mf5+ZEA== +"@storybook/core-server@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.19.tgz#0d1b4b2094749b8bce03e3d01422e14e5fef8e66" + integrity sha512-bKsUB9f7hl5ya2JXxpIrErmbDQjoH39FVbzYZWjMo4t/b7+Xyi6vYadwyWcqlpUQmis09ZaSMv8L/Tw0TuwLAA== dependencies: "@discoveryjs/json-ext" "^0.5.3" - "@storybook/builder-webpack4" "6.4.18" - "@storybook/core-client" "6.4.18" - "@storybook/core-common" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/builder-webpack4" "6.4.19" + "@storybook/core-client" "6.4.19" + "@storybook/core-common" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/csf-tools" "6.4.18" - "@storybook/manager-webpack4" "6.4.18" - "@storybook/node-logger" "6.4.18" + "@storybook/csf-tools" "6.4.19" + "@storybook/manager-webpack4" "6.4.19" + "@storybook/node-logger" "6.4.19" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.18" + "@storybook/store" "6.4.19" "@types/node" "^14.0.10" "@types/node-fetch" "^2.5.7" "@types/pretty-hrtime" "^1.0.0" @@ -1742,18 +1742,18 @@ webpack "4" ws "^8.2.3" -"@storybook/core@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/core/-/core-6.4.18.tgz#56f7bb0f20dbcfa205d860022b7bf30bf42fd472" - integrity sha512-7DTMAEXiBIwd1jgalbsZiXCiS2Be9MKKsr6GQdf3WaBm0WYV067oN9jcUY5IgNtJX06arT4Ykp+CGG/TR+sLlw== +"@storybook/core@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/core/-/core-6.4.19.tgz#58dd055bcc0ef335e0e0d3f6eca74b4d4d49eba1" + integrity sha512-55LOQ/h/kf1jMhjN85t/pIEdIwWEG9yV7bdwv3niVvmoypCxyyjn9/QNK0RKYAeDSUtdm6FVoJ6k5CpxWz2d8w== dependencies: - "@storybook/core-client" "6.4.18" - "@storybook/core-server" "6.4.18" + "@storybook/core-client" "6.4.19" + "@storybook/core-server" "6.4.19" -"@storybook/csf-tools@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.18.tgz#cdd40b543f9bea79c1481c236868b8ea04af6bd7" - integrity sha512-KtwxKrkndEyvyAiBliI6m4yMFMvnyI4fOjU8t1qCit/0gjutOF5JxmmZ+H8FSI5dIyibEOzQmzHe0MyStAjCEQ== +"@storybook/csf-tools@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.19.tgz#28bdea11da17501a8bc4e761b821d7721880eaf6" + integrity sha512-gf/zRhGoAVsFwSyV2tc+jeJfZQkxF6QsaZgbUSe24/IUvGFCT/PS/jZq1qy7dECAwrTOfykgu8juyBtj6WhWyw== dependencies: "@babel/core" "^7.12.10" "@babel/generator" "^7.12.11" @@ -1780,20 +1780,20 @@ dependencies: lodash "^4.17.15" -"@storybook/manager-webpack4@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.18.tgz#5317c917dbdaf4cf8721647551a785eb13c04146" - integrity sha512-6oX1KrIJBoY4vdZiMftJNusv+Bm8pegVjdJ+aZcbr/41x7ufP3tu5UKebEXDH0UURXtLw0ffl+OgojewGdpC1Q== +"@storybook/manager-webpack4@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.19.tgz#999577afb9b9a57fc478f7c5e5d95d785ea69da3" + integrity sha512-R8ugZjTYqXvlc6gDOcw909L65sIleOmIJLZR+N6/H85MivGXHu39jOwONqB7tVACufRty4FNecn8tEiQL2SAKA== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-transform-template-literals" "^7.12.1" "@babel/preset-react" "^7.12.10" - "@storybook/addons" "6.4.18" - "@storybook/core-client" "6.4.18" - "@storybook/core-common" "6.4.18" - "@storybook/node-logger" "6.4.18" - "@storybook/theming" "6.4.18" - "@storybook/ui" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/core-client" "6.4.19" + "@storybook/core-common" "6.4.19" + "@storybook/node-logger" "6.4.19" + "@storybook/theming" "6.4.19" + "@storybook/ui" "6.4.19" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" babel-loader "^8.0.0" @@ -1822,10 +1822,10 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" -"@storybook/node-logger@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.18.tgz#8759761ba7526b2fa03a1a08fe82d6d892d7a072" - integrity sha512-wY1qt4XOXtJJdQ+DrO3RijtiwVFqWuWetvCY4RV4lge5yk0FP5Q+MTpmjazYodAvGPUIP0LK9bvEDLwXa0JUfw== +"@storybook/node-logger@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.19.tgz#554f9efad4e95ce6fa63222d026f43258293c896" + integrity sha512-hO2Aar3PgPnPtNq2fVgiuGlqo3EEVR6TKVBXMq7foL3tN2k4BQFKLDHbm5qZQQntyYKurKsRUGKPJFPuI1ov/w== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.1.0" @@ -1833,17 +1833,17 @@ npmlog "^5.0.1" pretty-hrtime "^1.0.3" -"@storybook/preview-web@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.18.tgz#47c908bf27d2089ccf3296c376a6f5b1e8674b5a" - integrity sha512-0x64uLdGhIOk9hIuRKTHFdP7+iEHyjAOi5U4jtwqFfDtG4n4zxEGSsUWij7pTR2rAYf7g2NWIbAM7qb1AqqcLQ== +"@storybook/preview-web@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.19.tgz#bdfab7b2f760caf72140229dd64fd57617ad000b" + integrity sha512-jqltoBv5j7lvnxEfV9w8dLX9ASWGuvgz97yg8Yo5FqkftEwrHJenyvMGcTgDJKJPorF+wiz/9aIqnmd3LCAcZQ== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/channel-postmessage" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/channel-postmessage" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/store" "6.4.18" + "@storybook/store" "6.4.19" ansi-to-html "^0.6.11" core-js "^3.8.2" global "^4.4.0" @@ -1868,22 +1868,22 @@ react-docgen-typescript "^2.0.0" tslib "^2.0.0" -"@storybook/react@^6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/react/-/react-6.4.18.tgz#22624af56a9873c6616b5dc6a1e30c968bac95d2" - integrity sha512-dKxwsvJEGTm/aNIJSJMI4MImsI4EhmBa42FtwVvtFkrokuMf2CsmTJsaaAh+1or9SKGTiFuGsYDGhX5joE3XUQ== +"@storybook/react@^6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/react/-/react-6.4.19.tgz#1707b785b5a65c867e291ede12113e7fd55f8998" + integrity sha512-5b3i8jkVrjQGmcxxxXwCduHPIh+cluWkfeweKeQOe+lW4BR8fuUICo3AMLrYPAtB/UcaJyYkIYmTvF2mkfepFA== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.10" "@pmmmwh/react-refresh-webpack-plugin" "^0.5.1" - "@storybook/addons" "6.4.18" - "@storybook/core" "6.4.18" - "@storybook/core-common" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/core" "6.4.19" + "@storybook/core-common" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" - "@storybook/node-logger" "6.4.18" + "@storybook/node-logger" "6.4.19" "@storybook/react-docgen-typescript-plugin" "1.0.2-canary.253f8c1.0" "@storybook/semver" "^7.3.2" - "@storybook/store" "6.4.18" + "@storybook/store" "6.4.19" "@types/webpack-env" "^1.16.0" babel-plugin-add-react-displayname "^0.0.5" babel-plugin-named-asset-import "^0.3.1" @@ -1898,12 +1898,12 @@ ts-dedent "^2.0.0" webpack "4" -"@storybook/router@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/router/-/router-6.4.18.tgz#8803dd78277f8602d6c11dae56f6229474dfa54c" - integrity sha512-itvSWHhG1X/NV1sMlwP1qKtF0HfiIaAHImr0LwQ2K2F6/CI11W68dJAs4WBUdwzA0+H0Joyu/2a/6mCQHcee1A== +"@storybook/router@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/router/-/router-6.4.19.tgz#e653224dd9a521836bbd2610f604f609a2c77af2" + integrity sha512-KWWwIzuyeEIWVezkCihwY2A76Il9tUNg0I410g9qT7NrEsKyqXGRYOijWub7c1GGyNjLqz0jtrrehtixMcJkuA== dependencies: - "@storybook/client-logger" "6.4.18" + "@storybook/client-logger" "6.4.19" core-js "^3.8.2" fast-deep-equal "^3.1.3" global "^4.4.0" @@ -1923,13 +1923,13 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/source-loader@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.18.tgz#205423e56f7da752d64a0695f2b22ed94378e5d0" - integrity sha512-sjKvngCCYDbBwjjFTjAXO6VsAzKkjy+UctseeULXxEN3cKIsz/R3y7MrrN9yBrwyYcn0k3pqa9d9e3gE+Jv2Tw== +"@storybook/source-loader@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.19.tgz#24d134750bc41a13255b2b4a545f2d82613f004f" + integrity sha512-XqTsqddRglvfW7mhyjwoqd/B8L6samcBehhO0OEbsFp6FPWa9eXuObCxtRYIcjcSIe+ksbW3D/54ppEs1L/g1Q== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/client-logger" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/client-logger" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" core-js "^3.8.2" estraverse "^5.2.0" @@ -1939,14 +1939,14 @@ prettier ">=2.2.1 <=2.3.0" regenerator-runtime "^0.13.7" -"@storybook/store@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/store/-/store-6.4.18.tgz#3b693c9d5555d5cfc04e2318e104746d9d55ad66" - integrity sha512-Vl5oCs/9fP1gUgfgMHTBsnYbwAAoaR93/bzDBeOHI3eo5x9uzzJtA4zcRmEiKahR/wgwGacpWy90JrIX469PDQ== +"@storybook/store@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz#bf4031499f4d49909d7b691c03cc5ef1ec00ad74" + integrity sha512-N9/ZjemRHGfT3InPIbqQqc6snkcfnf3Qh9oOr0smbfaVGJol//KOX65kzzobtzFcid0WxtTDZ3HmgFVH+GvuhQ== dependencies: - "@storybook/addons" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/core-events" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/core-events" "6.4.19" "@storybook/csf" "0.0.2--canary.87bc651.0" core-js "^3.8.2" fast-deep-equal "^3.1.3" @@ -1960,15 +1960,15 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/theming@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.18.tgz#05365cc1d3dab5d71b80a82928fc5188106a0ed6" - integrity sha512-1o0w2eP+8sXUesdtXpZR4Yvayp1h3xvK7l9+wuHh+1uCy+EvD5UI9d1HvU5kt5fw7XAJJcInaVAmyAbpwct0TQ== +"@storybook/theming@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.19.tgz#0a6834d91e0b0eadbb10282e7fb2947e2bbf9e9e" + integrity sha512-V4pWmTvAxmbHR6B3jA4hPkaxZPyExHvCToy7b76DpUTpuHihijNDMAn85KhOQYIeL9q14zP/aiz899tOHsOidg== dependencies: "@emotion/core" "^10.1.1" "@emotion/is-prop-valid" "^0.8.6" "@emotion/styled" "^10.0.27" - "@storybook/client-logger" "6.4.18" + "@storybook/client-logger" "6.4.19" core-js "^3.8.2" deep-object-diff "^1.1.0" emotion-theming "^10.0.27" @@ -1978,21 +1978,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.4.18": - version "6.4.18" - resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.18.tgz#3ceaf6b317f8f2c1d7d1cdc49daaac7eaf10af6b" - integrity sha512-f2ckcLvEyA9CRcu6W2I2CyEbUnU4j3h5Nz0N40YZ2uRMVNQY2xPywAFZVySZIJAaum/5phDfnOD0Feap/Q6zVQ== +"@storybook/ui@6.4.19": + version "6.4.19" + resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.19.tgz#1fb9f6cd875ee4937cf9d81ca45d5156800176d1" + integrity sha512-gFwdn5LA2U6oQ4bfUFLyHZnNasGQ01YVdwjbi+l6yjmnckBNtZfJoVTZ1rzGUbxSE9rK48InJRU+latTsr7xAg== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.4.18" - "@storybook/api" "6.4.18" - "@storybook/channels" "6.4.18" - "@storybook/client-logger" "6.4.18" - "@storybook/components" "6.4.18" - "@storybook/core-events" "6.4.18" - "@storybook/router" "6.4.18" + "@storybook/addons" "6.4.19" + "@storybook/api" "6.4.19" + "@storybook/channels" "6.4.19" + "@storybook/client-logger" "6.4.19" + "@storybook/components" "6.4.19" + "@storybook/core-events" "6.4.19" + "@storybook/router" "6.4.19" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.4.18" + "@storybook/theming" "6.4.19" copy-to-clipboard "^3.3.1" core-js "^3.8.2" core-js-pure "^3.8.2" @@ -7859,10 +7859,10 @@ store2@^2.12.0: resolved "https://registry.npmjs.org/store2/-/store2-2.13.1.tgz#fae7b5bb9d35fc53dc61cd262df3abb2f6e59022" integrity sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg== -storybook-dark-mode@^1.0.8: - version "1.0.8" - resolved "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.0.8.tgz#bbd64b382fd62d38685fdd769e2cac4e32ec293d" - integrity sha512-uY6yTSd1vYE0YwlON50u+iIoNF/fmMj59ww1cpd/naUcmOmCjwawViKFG5YjichwdR/yJ5ybWRUF0tnRQfaSiw== +storybook-dark-mode@^1.0.9: + version "1.0.9" + resolved "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.0.9.tgz#40c15aa340bc700df2fb4f1345250e6fdace0b3a" + integrity sha512-ITPXM2OSaga1zM5blpZy5HxMWAhrAqYi9aJtLgRtSdgoRrxVNAInDRD14TjmObdgLHNWxINoNbnEB+sKETa+iw== dependencies: fast-deep-equal "^3.0.0" memoizerific "^1.11.3" diff --git a/yarn.lock b/yarn.lock index d4357ea49e..96b29fc341 100644 --- a/yarn.lock +++ b/yarn.lock @@ -122,16 +122,17 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/core-client@^1.0.0": - version "1.2.2" - resolved "https://registry.npmjs.org/@azure/core-client/-/core-client-1.2.2.tgz#29c781e5ccd4da968cea89d3b909ab573a3a7bec" - integrity sha512-VYFR2qiczjBrSfpQSbo5s8FJhXaJFz2tP01MOrpNJaOqnSNEKcY35I79b1Ty7s8qHGvc5/YMJ745l3B7abncFQ== +"@azure/core-client@^1.4.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@azure/core-client/-/core-client-1.5.0.tgz#7aabb87d20e08db3683a117191c844bc19adb74e" + integrity sha512-YNk8i9LT6YcFdFO+RRU0E4Ef+A8Y5lhXo6lz61rwbG8Uo7kSqh0YqK04OexiilM43xd6n3Y9yBhLnb1NFNI9dA== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-asynciterator-polyfill" "^1.0.0" "@azure/core-auth" "^1.3.0" - "@azure/core-rest-pipeline" "^1.1.0" - "@azure/core-tracing" "1.0.0-preview.12" + "@azure/core-rest-pipeline" "^1.5.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" tslib "^2.2.0" "@azure/core-http@^1.2.0": @@ -172,16 +173,16 @@ dependencies: "@azure/core-asynciterator-polyfill" "^1.0.0" -"@azure/core-rest-pipeline@^1.1.0": - version "1.1.1" - resolved "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.1.1.tgz#53b4278f5c417c3da9f133511064375362b68a12" - integrity sha512-ObF8iTEDXIG7/NlL28ni9bR3XLJwgm2S3GWO4aNW6CsTCFVoY9HMdbBtN7xOB+pUQwifehifXNnootbzzuwJnw== +"@azure/core-rest-pipeline@^1.1.0", "@azure/core-rest-pipeline@^1.5.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.5.0.tgz#6f3989bd2cad581adb982885f836c00dacd78336" + integrity sha512-Lofjl3mu1TULhjxoPKY4IqXt6mC8Q+r3xMF1dOz0D/aElKfrbqtO2fts36PCClAq+DJzQM/kbnrNTf3X601I5w== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.3.0" - "@azure/core-tracing" "1.0.0-preview.12" + "@azure/core-tracing" "1.0.0-preview.13" "@azure/logger" "^1.0.0" - form-data "^3.0.0" + form-data "^4.0.0" http-proxy-agent "^4.0.1" https-proxy-agent "^5.0.0" tslib "^2.2.0" @@ -196,14 +197,6 @@ "@opentelemetry/api" "^0.10.2" tslib "^2.0.0" -"@azure/core-tracing@1.0.0-preview.12": - version "1.0.0-preview.12" - resolved "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.12.tgz#f53ff452c0742ad981c244f97d93d37ca2b5e139" - integrity sha512-nvo2Wc4EKZGN6eFu9n3U7OXmASmL8VxoPIH7xaD6OlQqi44bouF0YIi9ID5rEsKLiAU59IYx6M297nqWVMWPDg== - dependencies: - "@opentelemetry/api" "^1.0.0" - tslib "^2.2.0" - "@azure/core-tracing@1.0.0-preview.13": version "1.0.0-preview.13" resolved "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" @@ -229,13 +222,13 @@ tslib "^2.0.0" "@azure/identity@^2.0.1": - version "2.0.1" - resolved "https://registry.npmjs.org/@azure/identity/-/identity-2.0.1.tgz#31107506371e520bc874647a9e4384cfd2f85103" - integrity sha512-gdGGuLKlKIQaf2RefA84keoBfmWfiAntbW2SzcdKvwLSGzsio/qkyY3sYUpXRz/sqLDxguuimgZukp7TPgwIlg== + version "2.0.3" + resolved "https://registry.npmjs.org/@azure/identity/-/identity-2.0.3.tgz#286e7b145b29bee009ef10f3c2900122dcc1c947" + integrity sha512-MFW2QS5dWm2U8MDTSm0sHo7pcAQtQtJhKVVcN5wA2ownHzmHluXTGFK4WdFiXzUInhZtqYA5CH+OGHTGs6DTBA== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.3.0" - "@azure/core-client" "^1.0.0" + "@azure/core-client" "^1.4.0" "@azure/core-rest-pipeline" "^1.1.0" "@azure/core-tracing" "1.0.0-preview.13" "@azure/core-util" "^1.0.0-beta.1" @@ -243,7 +236,6 @@ "@azure/msal-browser" "^2.16.0" "@azure/msal-common" "^4.5.1" "@azure/msal-node" "^1.3.0" - "@types/stoppable" "^1.1.0" events "^3.0.0" jws "^4.0.0" open "^8.0.0" @@ -323,7 +315,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== -"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.15.5", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.13.16", "@babel/core@^7.14.0", "@babel/core@^7.15.5", "@babel/core@^7.7.5": version "7.16.12" resolved "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== @@ -1049,7 +1041,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-react-constant-elements@^7.12.1": +"@babel/plugin-transform-react-constant-elements@^7.14.5": version "7.16.7" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== @@ -1163,7 +1155,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/preset-env@^7.12.1": +"@babel/preset-env@^7.15.6": version "7.16.11" resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== @@ -1263,7 +1255,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.5": +"@babel/preset-react@^7.14.5": version "7.16.7" resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== @@ -1275,7 +1267,7 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.7" "@babel/plugin-transform-react-pure-annotations" "^7.16.7" -"@babel/preset-typescript@^7.13.0": +"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": version "7.16.7" resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== @@ -1358,7 +1350,7 @@ "@babel/helper-validator-identifier" "^7.15.7" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.16.8" resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== @@ -1366,21 +1358,17 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@backstage/core-plugin-api@^0.4.0", "@backstage/core-plugin-api@^0.4.1": - version "0.4.1" - resolved "https://registry.npmjs.org/@backstage/core-plugin-api/-/core-plugin-api-0.4.1.tgz#c0a13504bdfa61ae3d0db96934cd6c32a7574446" - integrity sha512-IIb7XTcquTPaSIlamMKUgeTs5uLqkKN0Nw32QdTZhKgFkFFVzWC0AwN+henkaMNBZFdGb0ttPzrvNXGj5E6dGg== +"@backstage/catalog-model@^0.9.7": + version "0.10.0" dependencies: - "@backstage/config" "^0.1.11" - "@backstage/theme" "^0.2.14" - "@backstage/types" "^0.1.1" - "@backstage/version-bridge" "^0.1.1" - "@material-ui/core" "^4.12.2" - history "^5.0.0" - prop-types "^15.7.2" - react-router-dom "6.0.0-beta.0" - react-use "^17.2.4" - zen-observable "^0.8.15" + "@backstage/config" "^0.1.14" + "@backstage/errors" "^0.2.1" + "@backstage/types" "^0.1.2" + "@types/json-schema" "^7.0.5" + ajv "^7.0.3" + json-schema "^0.4.0" + lodash "^4.17.21" + uuid "^8.0.0" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" @@ -1736,14 +1724,14 @@ dependencies: "@date-io/core" "^1.3.13" -"@elastic/elasticsearch-mock@^0.3.0": - version "0.3.0" - resolved "https://registry.npmjs.org/@elastic/elasticsearch-mock/-/elasticsearch-mock-0.3.0.tgz#6b1d8448aad3ca20f760fa01c0206b733c9c1e54" - integrity sha512-hZYRjPgRE1M0wCqdsgaDtwxrgQEXDZya1gQ3gnpc8pB8mHUfPoO+9ye7GbDPUkWbuGGGZ4/p6OKmAbt/ME+CDQ== +"@elastic/elasticsearch-mock@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@elastic/elasticsearch-mock/-/elasticsearch-mock-1.0.0.tgz#1fbaf6bf220cd74a34494ff3a8673551d9dfc66f" + integrity sha512-MajkXUZ1xMYJilZc4f6KxZ9fbOp3VkUgjshZOm3Z4dbzEpRz7FinOfo6/Om7qdFyzhCJ9GgPQz4b0zp+3QMeqQ== dependencies: - fast-deep-equal "^3.1.1" - find-my-way "^2.2.2" - into-stream "^5.1.1" + fast-deep-equal "^3.1.3" + find-my-way "^4.3.3" + into-stream "^6.0.0" "@elastic/elasticsearch@7.13.0": version "7.13.0" @@ -1809,12 +1797,12 @@ query-string "^7.0.0" xcase "^2.0.1" -"@gitbeaker/core@^35.1.0": - version "35.1.0" - resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-35.1.0.tgz#57f294886451b5ab2bccf0fc5fd8f6507473cd3a" - integrity sha512-DM9w3wgrS8GoXMLJb0DL2VSxTvP3yoaGDfX2d8n3wMGSjZbCknh3YnbVG/OfnaPbh9PH71kGll3SY5rJgz7XJg== +"@gitbeaker/core@^35.4.0": + version "35.4.0" + resolved "https://registry.npmjs.org/@gitbeaker/core/-/core-35.4.0.tgz#ebc3e46f9d8e17f85f81ccfe163cffdcd429545a" + integrity sha512-VjRmC/j1umhn0+f+DbrbxXDAc0uvGd32tJ4MCFQYkxw9ndr/0Rlg8iYvYN/zWyqtgr3SeTxMyS3Z9MtbWWhjBA== dependencies: - "@gitbeaker/requester-utils" "^35.1.0" + "@gitbeaker/requester-utils" "^35.4.0" form-data "^4.0.0" li "^1.3.0" mime "^3.0.0" @@ -1822,14 +1810,14 @@ xcase "^2.0.1" "@gitbeaker/node@^35.1.0": - version "35.1.0" - resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-35.1.0.tgz#a3b2d96534b54d8e3a3c8130da82ebc8802257d8" - integrity sha512-t0lXqSuY93jVffo6WMeo4tvZtkMQXPKuGb1qNh3HOuW4+KyEqmrdQnorGyyRYH7uRTmQeHEe33BL1Ttc5F5YrA== + version "35.4.0" + resolved "https://registry.npmjs.org/@gitbeaker/node/-/node-35.4.0.tgz#096a28fd936dad9220625a917502063adf566acf" + integrity sha512-5isY4/ePtjIs7uFwVW8U5oNNwntyCa3eTs3+tb6CywtLGdlnenk0eNJjZ2Srn8xJOKsOCCpQkT5hP1AOKSAlAQ== dependencies: - "@gitbeaker/core" "^35.1.0" - "@gitbeaker/requester-utils" "^35.1.0" + "@gitbeaker/core" "^35.4.0" + "@gitbeaker/requester-utils" "^35.4.0" delay "^5.0.0" - got "^11.8.2" + got "11.8.3" xcase "^2.0.1" "@gitbeaker/requester-utils@^34.6.0": @@ -1841,10 +1829,10 @@ qs "^6.10.1" xcase "^2.0.1" -"@gitbeaker/requester-utils@^35.1.0": - version "35.1.0" - resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-35.1.0.tgz#98c049d6b4e3f5ce222d7376b605e15c59d7bc93" - integrity sha512-00aQYCxs3wBHrD5HGWh0l1FRsX1NYJ1GEq4Reyo1NpVgjwzO/T1jjMFy3jikjJ+UGeg0sfqV9h91mwtCQ4SmRA== +"@gitbeaker/requester-utils@^35.4.0": + version "35.4.0" + resolved "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-35.4.0.tgz#918be27441024c841d3f9e09c498e6b24de291e2" + integrity sha512-NkJ55oMM7TNMWUNnzeYLdLOIUFv1LBBN/PCM2u7J5+67gpck03YfWAkgrODIqBePFyrfm19pdka3SUlNBP0G2g== dependencies: form-data "^4.0.0" qs "^6.10.1" @@ -2510,15 +2498,14 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@hot-loader/react-dom@^16.13.0": - version "16.13.0" - resolved "https://registry.npmjs.org/@hot-loader/react-dom/-/react-dom-16.13.0.tgz#de245b42358110baf80aaf47a0592153d4047997" - integrity sha512-lJZrmkucz2MrQJTQtJobx5MICXcfQvKihszqv655p557HPi0hMOWxrNpiHv3DWD8ugNWjtWcVWqRnFvwsHq1mQ== +"@hot-loader/react-dom@^17.0.2": + version "17.0.2" + resolved "https://registry.npmjs.org/@hot-loader/react-dom/-/react-dom-17.0.2.tgz#0b24e484093e8f97eb5c72bebdda44fc20bc8400" + integrity sha512-G2RZrFhsQClS+bdDh/Ojpk3SgocLPUGnvnJDTQYnmKSSwXtU+Yh+8QMs+Ia3zaAvBiOSpIIDSUxuN69cvKqrWg== dependencies: loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.19.0" + scheduler "^0.20.2" "@humanwhocodes/config-array@^0.9.2": version "0.9.2" @@ -2544,6 +2531,11 @@ resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== +"@isaacs/string-locale-compare@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b" + integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.0.0" resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b" @@ -3742,20 +3734,21 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" -"@npmcli/arborist@^2.2.2": - version "2.8.3" - resolved "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.3.tgz#5569e7d2038f6893abc81f9c879f497b506e6980" - integrity sha512-miFcxbZjmQqeFTeRSLLh+lc/gxIKDO5L4PVCp+dp+kmcwJmYsEJmF7YvHR2yi3jF+fxgvLf3CCFzboPIXAuabg== +"@npmcli/arborist@^4.0.4": + version "4.3.1" + resolved "https://registry.npmjs.org/@npmcli/arborist/-/arborist-4.3.1.tgz#a08cddce3339882f688c1dea1651f6971e781c44" + integrity sha512-yMRgZVDpwWjplorzt9SFSaakWx6QIK248Nw4ZFgkrAy/GvJaFRaSZzE6nD7JBK5r8g/+PTxFq5Wj/sfciE7x+A== dependencies: + "@isaacs/string-locale-compare" "^1.1.0" "@npmcli/installed-package-contents" "^1.0.7" - "@npmcli/map-workspaces" "^1.0.2" - "@npmcli/metavuln-calculator" "^1.1.0" + "@npmcli/map-workspaces" "^2.0.0" + "@npmcli/metavuln-calculator" "^2.0.0" "@npmcli/move-file" "^1.1.0" "@npmcli/name-from-folder" "^1.0.1" - "@npmcli/node-gyp" "^1.0.1" + "@npmcli/node-gyp" "^1.0.3" "@npmcli/package-json" "^1.0.1" - "@npmcli/run-script" "^1.8.2" - bin-links "^2.2.1" + "@npmcli/run-script" "^2.0.0" + bin-links "^3.0.0" cacache "^15.0.3" common-ancestor-path "^1.0.1" json-parse-even-better-errors "^2.3.1" @@ -3765,9 +3758,9 @@ npm-install-checks "^4.0.0" npm-package-arg "^8.1.5" npm-pick-manifest "^6.1.0" - npm-registry-fetch "^11.0.0" - pacote "^11.3.5" - parse-conflict-json "^1.1.1" + npm-registry-fetch "^12.0.1" + pacote "^12.0.2" + parse-conflict-json "^2.0.1" proc-log "^1.0.0" promise-all-reject-late "^1.0.0" promise-call-limit "^1.0.1" @@ -3814,23 +3807,24 @@ npm-bundled "^1.1.1" npm-normalize-package-bin "^1.0.1" -"@npmcli/map-workspaces@^1.0.2": - version "1.0.4" - resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz#915708b55afa25e20bc2c14a766c124c2c5d4cab" - integrity sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q== +"@npmcli/map-workspaces@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-2.0.0.tgz#e342efbbdd0dad1bba5d7723b674ca668bf8ac5a" + integrity sha512-QBJfpCY1NOAkkW3lFfru9VTdqvMB2TN0/vrevl5xBCv5Fi0XDVcA6rqqSau4Ysi4Iw3fBzyXV7hzyTBDfadf7g== dependencies: "@npmcli/name-from-folder" "^1.0.1" glob "^7.1.6" minimatch "^3.0.4" read-package-json-fast "^2.0.1" -"@npmcli/metavuln-calculator@^1.1.0": - version "1.1.1" - resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz#2f95ff3c6d88b366dd70de1c3f304267c631b458" - integrity sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ== +"@npmcli/metavuln-calculator@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-2.0.0.tgz#70937b8b5a5cad5c588c8a7b38c4a8bd6f62c84c" + integrity sha512-VVW+JhWCKRwCTE+0xvD6p3uV4WpqocNYYtzyvenqL/u1Q3Xx6fGTJ+6UoIoii07fbuEO9U3IIyuGY0CYHDv1sg== dependencies: cacache "^15.0.5" - pacote "^11.1.11" + json-parse-even-better-errors "^2.3.1" + pacote "^12.0.0" semver "^7.3.2" "@npmcli/move-file@^1.0.1": @@ -3853,10 +3847,10 @@ resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz#77ecd0a4fcb772ba6fe927e2e2e155fbec2e6b1a" integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== -"@npmcli/node-gyp@^1.0.1", "@npmcli/node-gyp@^1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz#3cdc1f30e9736dbc417373ed803b42b1a0a29ede" - integrity sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg== +"@npmcli/node-gyp@^1.0.2", "@npmcli/node-gyp@^1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33" + integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA== "@npmcli/package-json@^1.0.1": version "1.0.1" @@ -3884,6 +3878,16 @@ puka "^1.0.1" read-package-json-fast "^2.0.1" +"@npmcli/run-script@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@npmcli/run-script/-/run-script-2.0.0.tgz#9949c0cab415b17aaac279646db4f027d6f1e743" + integrity sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig== + dependencies: + "@npmcli/node-gyp" "^1.0.2" + "@npmcli/promise-spawn" "^1.3.2" + node-gyp "^8.2.0" + read-package-json-fast "^2.0.1" + "@octokit/app@^12.0.4": version "12.0.5" resolved "https://registry.npmjs.org/@octokit/app/-/app-12.0.5.tgz#0b25446daffcb36967b26944410eab1ccbba0c06" @@ -4272,11 +4276,6 @@ dependencies: "@opentelemetry/context-base" "^0.10.2" -"@opentelemetry/api@^1.0.0": - version "1.0.1" - resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.1.tgz#03c72f548431da5820a0c8864d1401e348e7e79f" - integrity sha512-H5Djcc2txGAINgf3TNaq4yFofYSIK3722PM89S/3R8FuI/eqi1UscajlXk7EBkG9s2pxss/q6SHlpturaavXaw== - "@opentelemetry/api@^1.0.1": version "1.0.4" resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.4.tgz#a167e46c10d05a07ab299fc518793b0cff8f6924" @@ -4345,6 +4344,18 @@ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= +"@react-hookz/deep-equal@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@react-hookz/deep-equal/-/deep-equal-1.0.1.tgz#1e9aad97b964879b54a3909f36f0727befa13e1f" + integrity sha512-6k/pU2jNlgYvKOy84vpCAZ8MGVwybvAdjzrh4UicCVOCPxz0LSBws1OE6O5TO4sPHaSw+yLfNzNK8RicGFc1Kw== + +"@react-hookz/web@^12.3.0": + version "12.3.0" + resolved "https://registry.npmjs.org/@react-hookz/web/-/web-12.3.0.tgz#a9a1311a15171a57d68a3db61492f913d4fd455a" + integrity sha512-Uujp2RfX/oDEtAbdkV0W/nhiQ5ZYVH+MEq04T7/8TstyiwoIlvsRbEic6c6gQA6sQ/lw93cZ8NP8R7AYjiqDvg== + dependencies: + "@react-hookz/deep-equal" "^1.0.1" + "@rjsf/core@^3.2.1": version "3.2.1" resolved "https://registry.npmjs.org/@rjsf/core/-/core-3.2.1.tgz#8a7b24c9a6f01f0ecb093fdfc777172c12b1b009" @@ -4365,14 +4376,14 @@ resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-3.2.1.tgz#84fbf322485aee3a84101e189161f0687779ec8d" integrity sha512-8UiDeDbjCImFSfOegGu13otQ7OdP9FOYpcLjeouppnhs+MPeIEAtYS+jCcBKmi3reyTagC15/KVSRhde1wS1vg== -"@roadiehq/backstage-plugin-buildkite@^1.3.4": - version "1.3.5" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.3.5.tgz#c8dd8390c4ca39dd522e481410d2be7fa79c0aec" - integrity sha512-KSITwXNK/sU//yHHrVizgGaHLXRDD2SVRDpwk35PFtY+iDM5msDVTcaGwNWJBOGVkegVTcq3cbHlGnEqm9AtNQ== +"@roadiehq/backstage-plugin-buildkite@^1.3.8": + version "1.3.8" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.3.8.tgz#fa91880e7d95a82d8d532f663cc9415c74dc6143" + integrity sha512-eZW826eMTgy7znkNRQzIhi/mlL6ztYRGq/+kThX3JjoHyGfIxEd+GnR58YEeuvs5dy277SJ/9gm3iibhK9T9sQ== dependencies: "@backstage/catalog-model" "^0.9.7" "@backstage/core-components" "^0.8.0" - "@backstage/core-plugin-api" "^0.4.0" + "@backstage/core-plugin-api" "^0.6.0" "@backstage/plugin-catalog-react" "^0.6.5" "@backstage/theme" "^0.2.6" "@material-ui/core" "^4.12.1" @@ -4384,14 +4395,14 @@ react-router-dom "6.0.0-beta.0" react-use "^17.2.4" -"@roadiehq/backstage-plugin-github-insights@^1.4.2": - version "1.4.4" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.4.4.tgz#a77671015cebae9a31133f07e7daa693f391b35c" - integrity sha512-867aiiP7w0mKHONHGgQaMKv3iczi+YGck4apUEj4UyRQkJd+D2W94bK2z3HI6fw0RInpqo383d5VE6Yq1TEJ2A== +"@roadiehq/backstage-plugin-github-insights@^1.5.0": + version "1.5.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.5.0.tgz#9a693be80adc9f3b9cfe5ba615628abde88e121f" + integrity sha512-r2FclGGF/6aTrT6wH5Xq+5ByfVwgCDt83+KINf1ELNuWt5x0nMtguSTyZqJ5n1AdbGybVJZ84dlfbSTa8RTU7g== dependencies: "@backstage/catalog-model" "^0.9.7" "@backstage/core-components" "^0.8.0" - "@backstage/core-plugin-api" "^0.4.0" + "@backstage/core-plugin-api" "^0.6.0" "@backstage/integration-react" "^0.1.10" "@backstage/plugin-catalog-react" "^0.6.5" "@backstage/theme" "^0.2.7" @@ -4399,16 +4410,19 @@ "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" + "@octokit/request-error" "^2.1.0" "@octokit/rest" "^18.5.3" "@octokit/types" "^6.14.2" history "^5.0.0" + immer "9.0.7" react-router "^6.0.0-beta.0" react-use "^17.2.4" + zustand "3.6.9" -"@roadiehq/backstage-plugin-github-pull-requests@^1.3.2": - version "1.3.7" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.3.7.tgz#d3c884c9b85f88c5f851f383596a616598c56076" - integrity sha512-a3PBLQ6SRtEDGNIekcGT8v4Aaac3BoEww/UU9uaQuE7bCEVolx2MeOVbSxb1uCWr6C6uGeDF5Kw4S4hPJJcnNg== +"@roadiehq/backstage-plugin-github-pull-requests@^1.4.0": + version "1.4.0" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.4.0.tgz#3f250c8b13c6b95ec2825f9b7088ea5199054013" + integrity sha512-qrbybOtZdWWWKptGfAvf1vzlwXGcvidWT5Dr6mbibn7GwSxSe4CD58pIEHJzFoT9jLHFGgAn5Uhh2SG/Ek7gbw== dependencies: "@backstage/catalog-model" "^0.9.7" "@backstage/core-components" "^0.8.0" @@ -4420,12 +4434,13 @@ "@octokit/types" "^5.0.1" "@types/node-fetch" "^2.5.7" history "^5.0.0" + lodash "^4.17.21" moment "^2.27.0" node-fetch "^2.6.1" react-router "6.0.0-beta.0" react-use "^17.2.4" -"@roadiehq/backstage-plugin-travis-ci@^1.3.2": +"@roadiehq/backstage-plugin-travis-ci@^1.3.6": version "1.3.6" resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.3.6.tgz#6f45a42bdf39aa6baab56f0c4400990238df1625" integrity sha512-th+2GaOjkPArDUbTBuhhCz/6WL4gcrVRVAsDHzuSrrJqNtsz6kXdBIHhR/58En16BZ2bnHhRzY87uiUDLjAntA== @@ -4647,100 +4662,46 @@ dependencies: loader-utils "^1.1.0" -"@svgr/babel-plugin-add-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" - integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== - "@svgr/babel-plugin-add-jsx-attribute@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== -"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" - integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== - "@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== -"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" - integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== - "@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== -"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": - version "5.0.1" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" - integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== - "@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== -"@svgr/babel-plugin-svg-dynamic-title@^5.4.0": - version "5.4.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" - integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== - "@svgr/babel-plugin-svg-dynamic-title@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== -"@svgr/babel-plugin-svg-em-dimensions@^5.4.0": - version "5.4.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" - integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== - "@svgr/babel-plugin-svg-em-dimensions@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== -"@svgr/babel-plugin-transform-react-native-svg@^5.4.0": - version "5.4.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" - integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== - "@svgr/babel-plugin-transform-react-native-svg@^6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== -"@svgr/babel-plugin-transform-svg-component@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" - integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== - "@svgr/babel-plugin-transform-svg-component@^6.2.0": version "6.2.0" resolved "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== -"@svgr/babel-preset@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" - integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1" - "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0" - "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0" - "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" - "@svgr/babel-plugin-transform-svg-component" "^5.5.0" - "@svgr/babel-preset@^6.2.0": version "6.2.0" resolved "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" @@ -4755,26 +4716,19 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0" -"@svgr/core@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" - integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ== +"@svgr/core@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61" + integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA== dependencies: - "@svgr/plugin-jsx" "^5.5.0" + "@svgr/plugin-jsx" "^6.2.1" camelcase "^6.2.0" - cosmiconfig "^7.0.0" + cosmiconfig "^7.0.1" -"@svgr/hast-util-to-babel-ast@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" - integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ== - dependencies: - "@babel/types" "^7.12.6" - -"@svgr/hast-util-to-babel-ast@^6.0.0": - version "6.0.0" - resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.0.0.tgz#423329ad866b6c169009cc82b5e28ffee80c857c" - integrity sha512-S+TxtCdDyRGafH1VG1t/uPZ87aOYOHzWL8kqz4FoSZcIbzWA6rnOmjNViNiDzqmEpzp2PW5o5mZfvC9DiVZhTQ== +"@svgr/hast-util-to-babel-ast@^6.0.0", "@svgr/hast-util-to-babel-ast@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25" + integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ== dependencies: "@babel/types" "^7.15.6" entities "^3.0.1" @@ -4789,17 +4743,17 @@ "@svgr/hast-util-to-babel-ast" "^6.0.0" svg-parser "^2.0.2" -"@svgr/plugin-jsx@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" - integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA== +"@svgr/plugin-jsx@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd" + integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g== dependencies: - "@babel/core" "^7.12.3" - "@svgr/babel-preset" "^5.5.0" - "@svgr/hast-util-to-babel-ast" "^5.5.0" + "@babel/core" "^7.15.5" + "@svgr/babel-preset" "^6.2.0" + "@svgr/hast-util-to-babel-ast" "^6.2.1" svg-parser "^2.0.2" -"@svgr/plugin-svgo@6.2.x": +"@svgr/plugin-svgo@6.2.x", "@svgr/plugin-svgo@^6.2.0": version "6.2.0" resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== @@ -4808,42 +4762,34 @@ deepmerge "^4.2.2" svgo "^2.5.0" -"@svgr/plugin-svgo@^5.5.0": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" - integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ== +"@svgr/rollup@6.2.x": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/rollup/-/rollup-6.2.1.tgz#23ac3173d2bd85842ca8858d3435332af1f064ab" + integrity sha512-5X6aMiGL1F5g0TubLY41GJ/Qf0Kz2xtbF37UbRJEHe2Z9CMlGl9Z3fQ8e28vmHrTptmymNRoHssgQ2Ejb1DARQ== dependencies: - cosmiconfig "^7.0.0" - deepmerge "^4.2.2" - svgo "^1.2.2" - -"@svgr/rollup@5.5.x": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/rollup/-/rollup-5.5.0.tgz#9ceaaa6d463916e69aff8a9e10b3bb8fbb94688a" - integrity sha512-EiZmH2VTr+Xzyb6Ga8XtGa9MEbiU3WQnB5vHmqhwAUqibU3uwuwr7MN+QwIh/gtBk1ucMim8BCfcRTlLVREM8A== - dependencies: - "@babel/core" "^7.12.3" - "@babel/plugin-transform-react-constant-elements" "^7.12.1" - "@babel/preset-env" "^7.12.1" - "@babel/preset-react" "^7.12.5" - "@svgr/core" "^5.5.0" - "@svgr/plugin-jsx" "^5.5.0" - "@svgr/plugin-svgo" "^5.5.0" + "@babel/core" "^7.15.5" + "@babel/plugin-transform-react-constant-elements" "^7.14.5" + "@babel/preset-env" "^7.15.6" + "@babel/preset-react" "^7.14.5" + "@babel/preset-typescript" "^7.16.0" + "@svgr/core" "^6.2.1" + "@svgr/plugin-jsx" "^6.2.1" + "@svgr/plugin-svgo" "^6.2.0" rollup-pluginutils "^2.8.2" -"@svgr/webpack@5.5.x": - version "5.5.0" - resolved "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" - integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g== +"@svgr/webpack@6.2.x": + version "6.2.1" + resolved "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d" + integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw== dependencies: - "@babel/core" "^7.12.3" - "@babel/plugin-transform-react-constant-elements" "^7.12.1" - "@babel/preset-env" "^7.12.1" - "@babel/preset-react" "^7.12.5" - "@svgr/core" "^5.5.0" - "@svgr/plugin-jsx" "^5.5.0" - "@svgr/plugin-svgo" "^5.5.0" - loader-utils "^2.0.0" + "@babel/core" "^7.15.5" + "@babel/plugin-transform-react-constant-elements" "^7.14.5" + "@babel/preset-env" "^7.15.6" + "@babel/preset-react" "^7.14.5" + "@babel/preset-typescript" "^7.15.0" + "@svgr/core" "^6.2.1" + "@svgr/plugin-jsx" "^6.2.1" + "@svgr/plugin-svgo" "^6.2.0" "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -5023,9 +4969,11 @@ integrity sha512-dB14TltT1SNq73z3MaZfKyyBZ37NAgAFl8jze59bisR4fJ6pB6AYGxItHFkooZbN7UcVJX/cFudM4p8wp1W4rA== "@types/aws4@^1.5.1": - version "1.5.2" - resolved "https://registry.npmjs.org/@types/aws4/-/aws4-1.5.2.tgz#34e35b4405a619b9205be3e7678963bc7c8a47db" - integrity sha512-r8+XOv0BKw3Br0oU6w9cfu21PaQq/5ZeXvMOivNQYJLc9WcPCpEFDaQu72QNEQjYv5Otu48VhjjnbtwrSmk/rg== + version "1.11.1" + resolved "https://registry.npmjs.org/@types/aws4/-/aws4-1.11.1.tgz#1783c88bd2a2fd0ad5ed497668a6d0df8d5f3c43" + integrity sha512-yUnPMlHP5JMZJiiNZElJG5qj1ShezlaET6Bug9SBhYsxKVamh7aOwl7Q/XR1Y//cZ5PoeRb9j4hi9svb2+FLlg== + dependencies: + "@types/node" "*" "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" @@ -5196,13 +5144,6 @@ resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== -"@types/cssnano@*": - version "5.0.0" - resolved "https://registry.npmjs.org/@types/cssnano/-/cssnano-5.0.0.tgz#9463679a7f11ea375e0ed4ada46c04de6c908ef0" - integrity sha512-z98V7ICNAojxj9YV9+Q8qV+F7fW0poLWJRjed9tu7KNdYzHwAvLOAsTMI8xWjkOY9yzO+HmMxRRixlIvRsZwXg== - dependencies: - postcss "^8" - "@types/d3-color@*": version "3.0.2" resolved "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.0.2.tgz#53f2d6325f66ee79afd707c05ac849e8ae0edbb0" @@ -5294,9 +5235,9 @@ "@types/d3-selection" "*" "@types/dagre@^0.7.44": - version "0.7.46" - resolved "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.46.tgz#c51ffcc62ca8a9affa07f5e06842acd840d3d442" - integrity sha512-ku3y+F8sPqmiB5Ugl22NpukI2dLAViJiWwdtueXLeuF4fxZozl+bytPSFVlLu/gDgaKiwobu3LBXXRWktIMiIA== + version "0.7.47" + resolved "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.47.tgz#1d1b89e1fac36aaf5ef5ed6274bb123073095ac5" + integrity sha512-oX+3aRf7L6Cqq1MvbWmmD7FpAU/T8URwFFuHBagAiyHILn3i+RNZ35/tvyq28de+lZGY3W19BxJ7FeITQDO7aA== "@types/debug@^4.0.0": version "4.1.7" @@ -5319,9 +5260,9 @@ "@types/ssh2" "*" "@types/dockerode@^3.2.5", "@types/dockerode@^3.3.0": - version "3.3.1" - resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.1.tgz#4b7e1b3c2b8636c3ef4f2628ca42d1d4bf78811d" - integrity sha512-pjEOl3C/N2viC+nU2iEM6ImFcyu/RoLZvfsAGc3xIW2MlyEox+ZtJgPDXCFfFVh8ZNouxCRL673aa2Ywbx20EQ== + version "3.3.3" + resolved "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.3.tgz#993de5d8bd3ecb0b0a9277cccc189e9a74e9fbd1" + integrity sha512-DBFTE/wiZKodQhDrdkzLVT3K0X1JO/1fTxPaTQN0jiPNdTOFoPt8LYnuYEzalPgVpZbGEeuJTls7qn6jMvuydg== dependencies: "@types/docker-modem" "*" "@types/node" "*" @@ -5333,10 +5274,10 @@ dependencies: "@types/trusted-types" "*" -"@types/eslint-scope@^3.7.0": - version "3.7.0" - resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.0.tgz#4792816e31119ebd506902a482caec4951fabd86" - integrity sha512-O/ql2+rrCUe2W2rs7wMR+GqPRcgB6UiqN5RhrR5xruFlY7l9YLMn0ZkDzjoHLeiFkR8MCQZVudUuuvQ2BLC9Qw== +"@types/eslint-scope@^3.7.3": + version "3.7.3" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== dependencies: "@types/eslint" "*" "@types/estree" "*" @@ -5357,10 +5298,10 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== +"@types/estree@*", "@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/estree@0.0.39": version "0.0.39" @@ -5903,11 +5844,6 @@ dependencies: "@types/node" "*" -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - "@types/qs@*": version "6.9.6" resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1" @@ -6055,21 +5991,19 @@ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/rollup-plugin-peer-deps-external@^2.2.0": - version "2.2.0" - resolved "https://registry.npmjs.org/@types/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.0.tgz#eae7d8b9d27fa037f5bcaded24e389f85b81973c" - integrity sha512-BiztED+KYJPBI3ihLSOuuZSzy836WAOpC9UrMtDqk3+VeByR8A5pJJ9pCVnq/dfB4wyCeiFL+FlyJnqZuP3pxg== + version "2.2.1" + resolved "https://registry.npmjs.org/@types/rollup-plugin-peer-deps-external/-/rollup-plugin-peer-deps-external-2.2.1.tgz#7711fe77727c2ec920d3e096fa4e61d02734a23d" + integrity sha512-CUK4Mi3M3A/0coRUeo4McvUFOxR5H6UYd6Wt3D+K4c4fJupolMSoIxsZaBG1g/BJQOaujf78Pf7KhgfhrX1FZA== dependencies: "@types/node" "*" rollup "^0.63.4" -"@types/rollup-plugin-postcss@^2.0.0": - version "2.0.1" - resolved "https://registry.npmjs.org/@types/rollup-plugin-postcss/-/rollup-plugin-postcss-2.0.1.tgz#f2c73a458b035db8af361c4a7d921f74c6d4dffa" - integrity sha512-q+o1V6536wwIIlwJzEjm09emg/1QIceJXo01h6fTA1JJY4p/QQTOc10mizp4NhmwRMB8LVOThCgkwvQgzvJFjQ== +"@types/rollup-plugin-postcss@^3.1.4": + version "3.1.4" + resolved "https://registry.npmjs.org/@types/rollup-plugin-postcss/-/rollup-plugin-postcss-3.1.4.tgz#064054efb779a4ab6f1ea5d67f46f26acfc13a51" + integrity sha512-r1udsfjOlDiErJAvpsU12LNqwYfaMtom4wTKkm8lAu/cZBYbEN7Mcfyucpicl+R3GoBkgNXE+39bEnMjXxGRdA== dependencies: - "@types/cssnano" "*" - "@types/node" "*" - rollup "^0.63.4" + rollup-plugin-postcss "*" "@types/scheduler@*": version "0.16.1" @@ -6196,6 +6130,13 @@ dependencies: "@types/superagent" "*" +"@types/svgo@^2.6.2": + version "2.6.2" + resolved "https://registry.npmjs.org/@types/svgo/-/svgo-2.6.2.tgz#97d8be0c50ff0562ed7522ba840149aee1c970e3" + integrity sha512-m1SqMc/EDAZ8v0BBX+NmlYytUXtvrMD2/J9LICwnMvAuJwb0GSmACU3XPvcORqE7ghEJA4Mk6NYzpwhQI/biPw== + dependencies: + "@types/node" "*" + "@types/swagger-ui-react@^4.1.1": version "4.1.1" resolved "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.1.1.tgz#6ae70f5b966941eb6655d79d1114d9b9ef69a980" @@ -6294,12 +6235,7 @@ "@types/expect" "^1.20.4" "@types/node" "*" -"@types/webpack-env@^1.15.2": - version "1.16.0" - resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz#8c0a9435dfa7b3b1be76562f3070efb3f92637b4" - integrity sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw== - -"@types/webpack-env@^1.15.3": +"@types/webpack-env@^1.15.2", "@types/webpack-env@^1.15.3": version "1.16.3" resolved "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a" integrity sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw== @@ -6696,13 +6632,13 @@ abstract-logging@^2.0.0: resolved "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.0.tgz#08a85814946c98ef06f4256ad470aba1886d4490" integrity sha512-/oA9z7JszpIioo6J6dB79LVUgJ3eD3cxkAmdCkvWWS+Y9tPtALs1rLqOekLUXUbYqM2fB9TTK0ibAyZJJOP/CA== -accepts@^1.3.5, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@^1.3.5, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-globals@^6.0.0: version "6.0.0" @@ -6766,10 +6702,10 @@ agent-base@^6.0.2: dependencies: debug "4" -agentkeepalive@^4.1.3, agentkeepalive@^4.1.4: - version "4.1.4" - resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" - integrity sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ== +agentkeepalive@^4.1.3, agentkeepalive@^4.1.4, agentkeepalive@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz#616ce94ccb41d1a39a45d203d8076fe98713062d" + integrity sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw== dependencies: debug "^4.1.0" depd "^1.1.2" @@ -7067,7 +7003,7 @@ aproba@^1.0.3: resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -aproba@^2.0.0: +"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== @@ -7106,13 +7042,21 @@ archiver@^5.0.2, archiver@^5.3.0: tar-stream "^2.2.0" zip-stream "^4.1.0" -are-we-there-yet@^1.1.5: - version "1.1.7" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146" - integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g== +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== dependencies: delegates "^1.0.0" - readable-stream "^2.0.6" + readable-stream "^3.6.0" + +are-we-there-yet@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" + integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" are-we-there-yet@~1.1.2: version "1.1.5" @@ -7734,17 +7678,17 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== -bin-links@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/bin-links/-/bin-links-2.2.1.tgz#347d9dbb48f7d60e6c11fe68b77a424bee14d61b" - integrity sha512-wFzVTqavpgCCYAh8SVBdnZdiQMxTkGR+T3b14CNpBXIBe2neJWaMGAZ55XWWHELJJ89dscuq0VCBqcVaIOgCMg== +bin-links@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bin-links/-/bin-links-3.0.0.tgz#8273063638919f6ba4fbe890de9438c1b3adf0b7" + integrity sha512-fC7kPWcEkAWBgCKxmAMqZldlIeHsXwQy9JXzrppAVQiukGiDKxmYesJcBKWu6UMwx/5GOfo10wtK/4zy+Xt/mg== dependencies: cmd-shim "^4.0.1" - mkdirp "^1.0.3" + mkdirp-infer-owner "^2.0.0" npm-normalize-package-bin "^1.0.0" read-cmd-shim "^2.0.0" rimraf "^3.0.0" - write-file-atomic "^3.0.3" + write-file-atomic "^4.0.0" binary-extensions@^2.0.0: version "2.0.0" @@ -7803,20 +7747,20 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -body-parser@1.19.1, body-parser@^1.19.0: - version "1.19.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== +body-parser@1.19.2, body-parser@^1.19.0: + version "1.19.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" + integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" depd "~1.1.2" http-errors "1.8.1" iconv-lite "0.4.24" on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + qs "6.9.7" + raw-body "2.4.3" type-is "~1.6.18" bonjour@^3.5.0: @@ -7831,7 +7775,7 @@ bonjour@^3.5.0: multicast-dns "^6.0.1" multicast-dns-service-types "^1.1.0" -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -7841,19 +7785,19 @@ bottleneck@^2.15.3: resolved "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== -boxen@^4.2.0: - version "4.2.0" - resolved "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" - integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== +boxen@^5.0.0: + version "5.1.2" + resolved "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== dependencies: ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^3.0.0" - cli-boxes "^2.2.0" - string-width "^4.1.0" - term-size "^2.1.0" - type-fest "^0.8.1" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" widest-line "^3.1.0" + wrap-ansi "^7.0.0" brace-expansion@^1.1.7: version "1.1.11" @@ -8090,7 +8034,12 @@ bytes@3.1.1: resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== -cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0: +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +cacache@^15.0.3, cacache@^15.0.5, cacache@^15.2.0, cacache@^15.3.0: version "15.3.0" resolved "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== @@ -8147,17 +8096,17 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -cacheable-request@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" - integrity sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw== +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== dependencies: clone-response "^1.0.2" get-stream "^5.1.0" http-cache-semantics "^4.0.0" keyv "^4.0.0" lowercase-keys "^2.0.0" - normalize-url "^4.1.0" + normalize-url "^6.0.1" responselike "^2.0.0" cachedir@^2.3.0: @@ -8251,12 +8200,12 @@ caniuse-lite@^1.0.30001286: integrity sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q== canvas@^2.6.1: - version "2.8.0" - resolved "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz#f99ca7f25e6e26686661ffa4fec1239bbef74461" - integrity sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q== + version "2.9.0" + resolved "https://registry.npmjs.org/canvas/-/canvas-2.9.0.tgz#7df0400b141a7e42e597824f377935ba96880f2a" + integrity sha512-0l93g7uxp7rMyr7H+XRQ28A3ud0dKIUTIEkUe1Dxh4rjUYN7B93+SjC3r1PDKA18xcQN87OFGgUnyw7LSgNLSQ== dependencies: "@mapbox/node-pre-gyp" "^1.0.0" - nan "^2.14.0" + nan "^2.15.0" simple-get "^3.0.3" capital-case@^1.0.4: @@ -8427,7 +8376,7 @@ check-types@^11.1.1: resolved "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f" integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ== -chokidar@^3.2.2, chokidar@^3.3.1, chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: +chokidar@^3.3.1, chokidar@^3.4.2, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -8521,10 +8470,10 @@ clean-stack@^2.0.0: resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== cli-cursor@^1.0.2: version "1.0.2" @@ -8687,15 +8636,6 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - code-error-fragment@0.0.230: version "0.0.230" resolved "https://registry.npmjs.org/code-error-fragment/-/code-error-fragment-0.0.230.tgz#d736d75c832445342eca1d1fedbf17d9618b14d7" @@ -8779,6 +8719,11 @@ color-string@^1.5.2, color-string@^1.6.0: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + color@3.0.x: version "3.0.0" resolved "https://registry.npmjs.org/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" @@ -9051,7 +8996,7 @@ console-browserify@^1.1.0: resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= @@ -9195,11 +9140,16 @@ cookie@0.4.0: resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== -cookie@0.4.1, cookie@^0.4.1, cookie@~0.4.1: +cookie@0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.4.2, cookie@^0.4.1, cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + cookiejar@^2.1.3: version "2.1.3" resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" @@ -9358,9 +9308,9 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cronstrue@^1.122.0: - version "1.123.0" - resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-1.123.0.tgz#de622dd8ea07981790f488d3f89a25e6e728ac8b" - integrity sha512-hVu9yNYRYr+jj5KET1p7FaBxFwtCHM1ByffP9lZ6yJ6p53u4VEmzH8117v9PUydxWNzc8Eq+sCZEzsKcB3ckiA== + version "1.125.0" + resolved "https://registry.npmjs.org/cronstrue/-/cronstrue-1.125.0.tgz#8030816d033d00caade9b2a9f9b71e69175bcf42" + integrity sha512-qkC5mVbVGuuyBVXmam5anaRtbLcgfBUKajoyZqCdf/XBdgF43PsLSEm8eEi2dsI3YbqDPbLSH2mWNzM1dVqHgQ== cross-env@^7.0.0: version "7.0.3" @@ -9376,7 +9326,7 @@ cross-fetch@3.1.4: dependencies: node-fetch "2.6.1" -cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.3, cross-fetch@^3.1.4, cross-fetch@^3.1.5: +cross-fetch@3.1.5, cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.3, cross-fetch@^3.1.4, cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -9497,34 +9447,19 @@ css-in-js-utils@^2.0.0: isobject "^3.0.1" css-loader@^6.5.1: - version "6.5.1" - resolved "https://registry.npmjs.org/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" - integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== + version "6.6.0" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-6.6.0.tgz#c792ad5510bd1712618b49381bd0310574fafbd3" + integrity sha512-FK7H2lisOixPT406s5gZM1S3l8GrfhEBT3ZiL2UX1Ng1XWs0y2GPllz/OTyvbaHe12VgQrIXIzuEGVlbUhodqg== dependencies: icss-utils "^5.1.0" - postcss "^8.2.15" + postcss "^8.4.5" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" postcss-modules-values "^4.0.0" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" semver "^7.3.5" -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - css-select@^4.1.3: version "4.1.3" resolved "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" @@ -9536,14 +9471,6 @@ css-select@^4.1.3: domutils "^2.6.0" nth-check "^2.0.0" -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== - dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" - css-tree@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/css-tree/-/css-tree-1.1.2.tgz#9ae393b5dafd7dae8a622475caec78d3d8fbd7b5" @@ -9573,11 +9500,6 @@ css-vendor@^2.0.8: "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" -css-what@^3.2.1: - version "3.4.2" - resolved "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" - integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== - css-what@^5.0.0: version "5.1.0" resolved "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" @@ -9657,13 +9579,6 @@ cssnano@^5.0.1: lilconfig "^2.0.3" yaml "^1.10.2" -csso@^4.0.2: - version "4.0.2" - resolved "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" - integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== - dependencies: - css-tree "1.0.0-alpha.37" - csso@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -10093,7 +10008,7 @@ debug@4.3.2: dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -10361,10 +10276,10 @@ detect-port-alt@^1.1.6: address "^1.0.1" debug "^2.6.0" -devtools-protocol@0.0.948846: - version "0.0.948846" - resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.948846.tgz#bff47e2d1dba060130fa40ed2e5f78b916ba285f" - integrity sha512-5fGyt9xmMqUl2VI7+rnUkKCiAQIpLns8sfQtTENy5L70ktbNw0Z3TFJ1JoFNYdx/jffz4YXU45VF75wKZD7sZQ== +devtools-protocol@0.0.960912: + version "0.0.960912" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz#411c1fa355eddb72f06c4a8743f2808766db6245" + integrity sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg== dezalgo@1.0.3, dezalgo@^1.0.0: version "1.0.3" @@ -10508,14 +10423,6 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.8.7" csstype "^2.6.7" -dom-serializer@0: - version "0.2.2" - resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - dom-serializer@^1.0.1: version "1.2.0" resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz#3433d9136aeb3c627981daa385fc7f32d27c48f1" @@ -10535,11 +10442,6 @@ domain-browser@^1.1.1: resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1: - version "1.3.1" - resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - domelementtype@^2.0.1, domelementtype@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" @@ -10577,17 +10479,9 @@ dompurify@=2.3.3: integrity sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg== dompurify@^2.2.7, dompurify@^2.2.9: - version "2.3.5" - resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.5.tgz#c83ed5a3ae5ce23e52efe654ea052ffb358dd7e3" - integrity sha512-kD+f8qEaa42+mjdOpKeztu9Mfx5bv9gVLO6K9jRx4uGvh6Wv06Srn4jr1wPNY2OOUGGSKHNFN+A8MA3v0E0QAQ== - -domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" + version "2.3.6" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875" + integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg== domutils@^2.5.2, domutils@^2.6.0: version "2.8.0" @@ -10850,7 +10744,7 @@ error@^10.4.0: resolved "https://registry.npmjs.org/error/-/error-10.4.0.tgz#6fcf0fd64bceb1e750f8ed9a3dd880f00e46a487" integrity sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw== -es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: +es-abstract@^1.17.0-next.1, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2: version "1.18.0" resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== @@ -10948,65 +10842,70 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -esbuild-android-arm64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.20.tgz#7d1e7391030d83e2d6745ac297d630bb33130b36" - integrity sha512-MPKVDe3TMjGDRB5WmY9XnBaXEsPiiTpkz6GjXgBhBkMFZm27PhvZT4JE0vZ1fsLb5hnGC/fYsfAnp9rsxTZhIg== +esbuild-android-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.22.tgz#fb051169a63307d958aec85ad596cfc7d7770303" + integrity sha512-k1Uu4uC4UOFgrnTj2zuj75EswFSEBK+H6lT70/DdS4mTAOfs2ECv2I9ZYvr3w0WL0T4YItzJdK7fPNxcPw6YmQ== -esbuild-darwin-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.20.tgz#b2633db8e87e36197965f18b6c0cfabc3497d8d2" - integrity sha512-09PPWejM3rRFsGHvtaTuRlG+KOQlOMwPW4HwwzRlO4TuP+FNV1nTW4x2Nid3dYLzCkcjznJWQ0oylLBQvGTRyQ== +esbuild-darwin-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.22.tgz#615ea0a9de67b57a293a7128d7ac83ee307a856d" + integrity sha512-d8Ceuo6Vw6HM3fW218FB6jTY6O3r2WNcTAU0SGsBkXZ3k8SDoRLd3Nrc//EqzdgYnzDNMNtrWegK2Qsss4THhw== -esbuild-darwin-arm64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.20.tgz#180fbebda4ec9376ffd8247a3d488f95c1d9df69" - integrity sha512-jYLrSXAwygoFF2lpRJSUAghre+9IThbcPvJQbcZMONBQaaZft9nclNsrN3k4u7zQaC8v+xZDVSHkmw593tQvkg== +esbuild-darwin-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.22.tgz#82054dcfcecb15ccfd237093b8008e7745a99ad9" + integrity sha512-YAt9Tj3SkIUkswuzHxkaNlT9+sg0xvzDvE75LlBo4DI++ogSgSmKNR6B4eUhU5EUUepVXcXdRIdqMq9ppeRqfw== -esbuild-freebsd-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.20.tgz#4eb99ccf3e0b7ab039e5bbe491a44458991006c2" - integrity sha512-XShznPLW3QsK8/7iCx1euZTowWaWlcrlkq4YTlRqDKXkJRe98FJ6+V2QyoSTwwCoo5koaYwc+h/SYdglF5369A== +esbuild-freebsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.22.tgz#778a818c5b078d5cdd6bb6c0e0797217d196999b" + integrity sha512-ek1HUv7fkXMy87Qm2G4IRohN+Qux4IcnrDBPZGXNN33KAL0pEJJzdTv0hB/42+DCYWylSrSKxk3KUXfqXOoH4A== -esbuild-freebsd-arm64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.20.tgz#5c6a02a4bc8ec8ff96c1142cf1509f1494aa78ff" - integrity sha512-flb3tDd6SScKhBqzWAESVCErpaqrGmMSRrssjx1aC+Ai5ZQrEyhfs5OWL4A9qHuixkhfmXffci7rFD+bNeXmZg== +esbuild-freebsd-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.22.tgz#18da93b9f3db2e036f72383bfe73b28b73bb332c" + integrity sha512-zPh9SzjRvr9FwsouNYTqgqFlsMIW07O8mNXulGeQx6O5ApgGUBZBgtzSlBQXkHi18WjrosYfsvp5nzOKiWzkjQ== -esbuild-linux-32@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.20.tgz#76af613e60a4f366d54d5d186c678bac36b18eda" - integrity sha512-Avtxbd0MHFJ2QhNxj/e8VGGm1/VnEJZq9qiHUl3wQZ4S0o2Wf4ReAfhqmgAbOPFTuxuZm070rRDZYiZifWzFGQ== +esbuild-linux-32@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.22.tgz#d0d5d9f5bb3536e17ac097e9512019c65b7c0234" + integrity sha512-SnpveoE4nzjb9t2hqCIzzTWBM0RzcCINDMBB67H6OXIuDa4KqFqaIgmTchNA9pJKOVLVIKd5FYxNiJStli21qg== -esbuild-linux-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.20.tgz#35d3c7d792403b913c308c92942c3f6893dc8225" - integrity sha512-ugisoRA/ajCr9JMszsQnT9hKkpbD7Gr1yl1mWdZhWQnGt6JKGIndGiihMURcrR44IK/2OMkixVe66D4gCHKdPA== +esbuild-linux-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.22.tgz#2773d540971999ea7f38107ef92fca753f6a8c30" + integrity sha512-Zcl9Wg7gKhOWWNqAjygyqzB+fJa19glgl2JG7GtuxHyL1uEnWlpSMytTLMqtfbmRykIHdab797IOZeKwk5g0zg== -esbuild-linux-arm64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.20.tgz#489e9187f95ce15e07e15a2aaadc53ec5ce1a02c" - integrity sha512-hsrMbNzhh+ud3zUyhONlR41vpYMjINS7BHEzXHbzo4YiCsG9Ht3arbiSuNGrhR/ybLr+8J/0fYVCipiVeAjy3Q== +esbuild-linux-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.22.tgz#5d4480ce6d6bffab1dd76a23158f5a5ab33e7ba4" + integrity sha512-8q/FRBJtV5IHnQChO3LHh/Jf7KLrxJ/RCTGdBvlVZhBde+dk3/qS9fFsUy+rs3dEi49aAsyVitTwlKw1SUFm+A== -esbuild-linux-arm@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.20.tgz#40c0f5aab33b8fe04e0528a6b8a073e9fb2ba6fd" - integrity sha512-uo++Mo31+P2EA38oQgOeSIWgD7GMCMpZkaLfsCqtKJTIIL9fVzQHQYLDRIiFGpLHvs1faWWHDCEcXEFSP1Ou0g== +esbuild-linux-arm@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.22.tgz#c6391b3f7c8fa6d3b99a7e893ce0f45f3a921eef" + integrity sha512-soPDdbpt/C0XvOOK45p4EFt8HbH5g+0uHs5nUKjHVExfgR7du734kEkXR/mE5zmjrlymk5AA79I0VIvj90WZ4g== -esbuild-linux-mips64le@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.20.tgz#3735a72ec09877b998f04c006af94f86575e4d7d" - integrity sha512-MBUu2Q+pzdTBWclPe7AwmRUMTUL0R99ONa8Hswpb987fXgFUdN4XBNBcEa5zy/l2UrIJK+9FUN1jjedZlxgP2A== +esbuild-linux-mips64le@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.22.tgz#2c8dabac355c502e86c38f9f292b3517d8e181f3" + integrity sha512-SiNDfuRXhGh1JQLLA9JPprBgPVFOsGuQ0yDfSPTNxztmVJd8W2mX++c4FfLpAwxuJe183mLuKf7qKCHQs5ZnBQ== -esbuild-linux-ppc64le@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.20.tgz#bf58bb6e9d2bfb67a61c09297cf73c3a7116935d" - integrity sha512-xkYjQtITA6q/b+/5aAf5n2L063pOxLyXUIad+zYT8GpZh0Sa7aSn18BmrFa2fHb0QSGgTEeRfYkTcBGgoPDjBA== +esbuild-linux-ppc64le@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.22.tgz#69d71b2820d5c94306072dac6094bae38e77d1c0" + integrity sha512-6t/GI9I+3o1EFm2AyN9+TsjdgWCpg2nwniEhjm2qJWtJyJ5VzTXGUU3alCO3evopu8G0hN2Bu1Jhz2YmZD0kng== -esbuild-linux-s390x@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.20.tgz#202699f42e5a7a77ebbf526953f6bbfb2cc68016" - integrity sha512-AAcj3x80TXIedpNVuZgjYNETXr2iciOBQv5pGdNGAy6rv7k6Y6sT6SXQ58l2LH2AHbaeTPQjze+Y6qgX1efzrA== +esbuild-linux-riscv64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.22.tgz#c0ec0fc3a23624deebf657781550d2329cec4213" + integrity sha512-AyJHipZKe88sc+tp5layovquw5cvz45QXw5SaDgAq2M911wLHiCvDtf/07oDx8eweCyzYzG5Y39Ih568amMTCQ== + +esbuild-linux-s390x@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.22.tgz#ec2af4572d63336cfb27f5a5c851fb1b6617dd91" + integrity sha512-Sz1NjZewTIXSblQDZWEFZYjOK6p8tV6hrshYdXZ0NHTjWE+lwxpOpWeElUGtEmiPcMT71FiuA9ODplqzzSxkzw== esbuild-loader@^2.18.0: version "2.18.0" @@ -11020,59 +10919,60 @@ esbuild-loader@^2.18.0: tapable "^2.2.0" webpack-sources "^2.2.0" -esbuild-netbsd-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.20.tgz#fb133b9726b8e672a7df57629fdc71606952d37c" - integrity sha512-30GQKCnsID1WddUi6tr5HFUxJD0t7Uitf6tO9Cf1WqF6C44pf8EflwrhyDFmUyvkddlyfb4OrYI6NNLC/G3ajg== +esbuild-netbsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.22.tgz#0e283278e9fdbaa7f0930f93ee113d7759cd865e" + integrity sha512-TBbCtx+k32xydImsHxvFgsOCuFqCTGIxhzRNbgSL1Z2CKhzxwT92kQMhxort9N/fZM2CkRCPPs5wzQSamtzEHA== -esbuild-openbsd-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.20.tgz#50e879a09bb465cda8c9a2f03ba5c2096848c7a1" - integrity sha512-zVrf8fY46BK57AkxDdqu2S8TV3p7oLmYIiW707IOHrveI0TwJ2iypAxnwOQuCvowM3UWqVBO2RDBzV7S7t0klg== +esbuild-openbsd-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.22.tgz#2a73bba04e16d8ef278fbe2be85248e12a2f2cc2" + integrity sha512-vK912As725haT313ANZZZN+0EysEEQXWC/+YE4rQvOQzLuxAQc2tjbzlAFREx3C8+uMuZj/q7E5gyVB7TzpcTA== -esbuild-sunos-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.20.tgz#cb1c55c86513226296935a9bc97fe9457b2a2de4" - integrity sha512-MYRsS1O7+aBr2T/0aA4OJrju6eMku4rm81fwGF1KLFwmymIpPGmj7n69n5JW3NKyW5j+FBt0GcyDh9nEnUL1FQ== +esbuild-sunos-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.22.tgz#8fe03513b8b2e682a6d79d5e3ca5849651a3c1d8" + integrity sha512-/mbJdXTW7MTcsPhtfDsDyPEOju9EOABvCjeUU2OJ7fWpX/Em/H3WYDa86tzLUbcVg++BScQDzqV/7RYw5XNY0g== -esbuild-windows-32@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.20.tgz#5e4db2758408e148e225f06c7724853386916c70" - integrity sha512-7VqDITqTU65LQ1Uka/4jx4sUIZc1L8NPlvc7HBRdR15TUyPxmHRQaxMGXd8aakI1FEBcImpJ9SQ4JLmPwRlS1w== +esbuild-windows-32@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.22.tgz#a75df61e3e49df292a1842be8e877a3153ee644f" + integrity sha512-1vRIkuvPTjeSVK3diVrnMLSbkuE36jxA+8zGLUOrT4bb7E/JZvDRhvtbWXWaveUc/7LbhaNFhHNvfPuSw2QOQg== -esbuild-windows-64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.20.tgz#0731564e8396091b2ac487fb266c86a2bdd45b37" - integrity sha512-q4GxY4m5+nXSgqCKx6Cc5pavnhd2g5mHn+K8kNdfCMZsWPDlHLMRjYF5NVQ3/5mJ1M7iR3/Ai4ISjxmsCeGOGA== +esbuild-windows-64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.22.tgz#d06cf8bbe4945b8bf95a730d871e54a22f635941" + integrity sha512-AxjIDcOmx17vr31C5hp20HIwz1MymtMjKqX4qL6whPj0dT9lwxPexmLj6G1CpR3vFhui6m75EnBEe4QL82SYqw== -esbuild-windows-arm64@0.14.20: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.20.tgz#615978735d3a8b5d0a8e4c35d5a18c0733920d4d" - integrity sha512-vOxfU7YwuBMjsUNUygMBhC8T60aCzeYptnHu4k7azqqOVo5EAyoueyWSkFR5GpX6bae5cXyB0vcOV/bfwqRwAg== +esbuild-windows-arm64@0.14.22: + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.22.tgz#f8b1b05c548073be8413a5ecb12d7c2f6e717227" + integrity sha512-5wvQ+39tHmRhNpu2Fx04l7QfeK3mQ9tKzDqqGR8n/4WUxsFxnVLfDRBGirIfk4AfWlxk60kqirlODPoT5LqMUg== esbuild@^0.14.1, esbuild@^0.14.10, esbuild@^0.14.6: - version "0.14.20" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.20.tgz#e83fcb838463f220e864141752bb0f91bfc9c33a" - integrity sha512-7aRJRnTjHZ6rFEre52tsAYZxatVELSA/QvYGUBf1iOsYKCnSJICE5seugQFFJgV1Gyl0/mngxQPhxBIqgYG2BA== + version "0.14.22" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.22.tgz#2b55fde89d7aa5aaaad791816d58ff9dfc5ed085" + integrity sha512-CjFCFGgYtbFOPrwZNJf7wsuzesx8kqwAffOlbYcFDLFuUtP8xloK1GH+Ai13Qr0RZQf9tE7LMTHJ2iVGJ1SKZA== optionalDependencies: - esbuild-android-arm64 "0.14.20" - esbuild-darwin-64 "0.14.20" - esbuild-darwin-arm64 "0.14.20" - esbuild-freebsd-64 "0.14.20" - esbuild-freebsd-arm64 "0.14.20" - esbuild-linux-32 "0.14.20" - esbuild-linux-64 "0.14.20" - esbuild-linux-arm "0.14.20" - esbuild-linux-arm64 "0.14.20" - esbuild-linux-mips64le "0.14.20" - esbuild-linux-ppc64le "0.14.20" - esbuild-linux-s390x "0.14.20" - esbuild-netbsd-64 "0.14.20" - esbuild-openbsd-64 "0.14.20" - esbuild-sunos-64 "0.14.20" - esbuild-windows-32 "0.14.20" - esbuild-windows-64 "0.14.20" - esbuild-windows-arm64 "0.14.20" + esbuild-android-arm64 "0.14.22" + esbuild-darwin-64 "0.14.22" + esbuild-darwin-arm64 "0.14.22" + esbuild-freebsd-64 "0.14.22" + esbuild-freebsd-arm64 "0.14.22" + esbuild-linux-32 "0.14.22" + esbuild-linux-64 "0.14.22" + esbuild-linux-arm "0.14.22" + esbuild-linux-arm64 "0.14.22" + esbuild-linux-mips64le "0.14.22" + esbuild-linux-ppc64le "0.14.22" + esbuild-linux-riscv64 "0.14.22" + esbuild-linux-s390x "0.14.22" + esbuild-netbsd-64 "0.14.22" + esbuild-openbsd-64 "0.14.22" + esbuild-sunos-64 "0.14.22" + esbuild-windows-32 "0.14.22" + esbuild-windows-64 "0.14.22" + esbuild-windows-arm64 "0.14.22" escalade@^3.1.1: version "3.1.1" @@ -11506,64 +11406,64 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" "example-app@link:packages/app": - version "0.2.64" + version "0.2.65" dependencies: - "@backstage/app-defaults" "^0.1.7" - "@backstage/catalog-model" "^0.9.10" - "@backstage/cli" "^0.13.2" - "@backstage/core-app-api" "^0.5.2" - "@backstage/core-components" "^0.8.8" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/integration-react" "^0.1.21" - "@backstage/plugin-airbrake" "^0.1.3" - "@backstage/plugin-apache-airflow" "^0.1.6" - "@backstage/plugin-api-docs" "^0.7.2" - "@backstage/plugin-azure-devops" "^0.1.14" - "@backstage/plugin-badges" "^0.2.22" - "@backstage/plugin-catalog" "^0.7.12" - "@backstage/plugin-catalog-common" "^0.1.2" - "@backstage/plugin-catalog-graph" "^0.2.10" - "@backstage/plugin-catalog-import" "^0.8.1" - "@backstage/plugin-catalog-react" "^0.6.14" - "@backstage/plugin-circleci" "^0.2.37" - "@backstage/plugin-cloudbuild" "^0.2.35" - "@backstage/plugin-code-coverage" "^0.1.25" - "@backstage/plugin-cost-insights" "^0.11.20" - "@backstage/plugin-explore" "^0.3.29" - "@backstage/plugin-gcp-projects" "^0.3.17" - "@backstage/plugin-github-actions" "^0.4.35" - "@backstage/plugin-gocd" "^0.1.4" - "@backstage/plugin-graphiql" "^0.2.30" - "@backstage/plugin-home" "^0.4.14" - "@backstage/plugin-jenkins" "^0.5.20" - "@backstage/plugin-kafka" "^0.2.28" - "@backstage/plugin-kubernetes" "^0.5.7" - "@backstage/plugin-lighthouse" "^0.2.37" - "@backstage/plugin-newrelic" "^0.3.16" - "@backstage/plugin-newrelic-dashboard" "^0.1.6" - "@backstage/plugin-org" "^0.4.2-next.0" - "@backstage/plugin-pagerduty" "0.3.25" - "@backstage/plugin-permission-react" "^0.3.0" - "@backstage/plugin-rollbar" "^0.3.26" - "@backstage/plugin-scaffolder" "^0.12.2" - "@backstage/plugin-search" "^0.6.2" - "@backstage/plugin-sentry" "^0.3.36" - "@backstage/plugin-shortcuts" "^0.1.22" - "@backstage/plugin-tech-insights" "^0.1.8" - "@backstage/plugin-tech-radar" "^0.5.5" - "@backstage/plugin-techdocs" "^0.13.3" - "@backstage/plugin-todo" "^0.2.0" - "@backstage/plugin-user-settings" "^0.3.19" - "@backstage/search-common" "^0.2.2" - "@backstage/theme" "^0.2.14" + "@backstage/app-defaults" "^0.1.8" + "@backstage/catalog-model" "^0.10.0" + "@backstage/cli" "^0.14.0" + "@backstage/core-app-api" "^0.5.3" + "@backstage/core-components" "^0.8.9" + "@backstage/core-plugin-api" "^0.6.1" + "@backstage/integration-react" "^0.1.22" + "@backstage/plugin-airbrake" "^0.2.0" + "@backstage/plugin-apache-airflow" "^0.1.7" + "@backstage/plugin-api-docs" "^0.7.3" + "@backstage/plugin-azure-devops" "^0.1.15" + "@backstage/plugin-badges" "^0.2.23" + "@backstage/plugin-catalog" "^0.8.0" + "@backstage/plugin-catalog-common" "^0.1.3" + "@backstage/plugin-catalog-graph" "^0.2.11" + "@backstage/plugin-catalog-import" "^0.8.2" + "@backstage/plugin-catalog-react" "^0.6.15" + "@backstage/plugin-circleci" "^0.2.38" + "@backstage/plugin-cloudbuild" "^0.2.36" + "@backstage/plugin-code-coverage" "^0.1.26" + "@backstage/plugin-cost-insights" "^0.11.21" + "@backstage/plugin-explore" "^0.3.30" + "@backstage/plugin-gcp-projects" "^0.3.18" + "@backstage/plugin-github-actions" "^0.4.36" + "@backstage/plugin-gocd" "^0.1.5" + "@backstage/plugin-graphiql" "^0.2.31" + "@backstage/plugin-home" "^0.4.15" + "@backstage/plugin-jenkins" "^0.5.21" + "@backstage/plugin-kafka" "^0.2.29" + "@backstage/plugin-kubernetes" "^0.5.8" + "@backstage/plugin-lighthouse" "^0.2.38" + "@backstage/plugin-newrelic" "^0.3.17" + "@backstage/plugin-newrelic-dashboard" "^0.1.7" + "@backstage/plugin-org" "^0.4.3" + "@backstage/plugin-pagerduty" "0.3.26" + "@backstage/plugin-permission-react" "^0.3.1" + "@backstage/plugin-rollbar" "^0.3.27" + "@backstage/plugin-scaffolder" "^0.12.3" + "@backstage/plugin-search" "^0.7.0" + "@backstage/plugin-sentry" "^0.3.37" + "@backstage/plugin-shortcuts" "^0.2.0" + "@backstage/plugin-tech-insights" "^0.1.9" + "@backstage/plugin-tech-radar" "^0.5.6" + "@backstage/plugin-techdocs" "^0.13.4" + "@backstage/plugin-todo" "^0.2.1" + "@backstage/plugin-user-settings" "^0.3.20" + "@backstage/search-common" "^0.2.3" + "@backstage/theme" "^0.2.15" "@material-ui/core" "^4.12.2" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.57" "@octokit/rest" "^18.5.3" - "@roadiehq/backstage-plugin-buildkite" "^1.3.4" - "@roadiehq/backstage-plugin-github-insights" "^1.4.2" - "@roadiehq/backstage-plugin-github-pull-requests" "^1.3.2" - "@roadiehq/backstage-plugin-travis-ci" "^1.3.2" + "@roadiehq/backstage-plugin-buildkite" "^1.3.8" + "@roadiehq/backstage-plugin-github-insights" "^1.5.0" + "@roadiehq/backstage-plugin-github-pull-requests" "^1.4.0" + "@roadiehq/backstage-plugin-travis-ci" "^1.3.6" history "^5.0.0" prop-types "^15.7.2" react "^17.0.2" @@ -11723,16 +11623,16 @@ express-xml-bodyparser@^0.3.0: xml2js "^0.4.11" express@^4.17.1: - version "4.17.2" - resolved "https://registry.npmjs.org/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== + version "4.17.3" + resolved "https://registry.npmjs.org/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" + integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.19.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.4.2" cookie-signature "1.0.6" debug "2.6.9" depd "~1.1.2" @@ -11747,7 +11647,7 @@ express@^4.17.1: parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.9.7" range-parser "~1.2.1" safe-buffer "5.2.1" send "0.17.2" @@ -11854,7 +11754,7 @@ extsprintf@^1.2.0: resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-decode-uri-component@^1.0.0: +fast-decode-uri-component@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== @@ -12090,12 +11990,13 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-my-way@^2.2.2: - version "2.2.5" - resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-2.2.5.tgz#86ce825266fa28cd962e538a45ec2aaa84c3d514" - integrity sha512-GjRZZlGcGmTh9t+6Xrj5K0YprpoAFCAiCPgmAH9Kb09O4oX6hYuckDfnDipYj+Q7B1GtYWSzDI5HEecNYscLQg== +find-my-way@^4.3.3: + version "4.5.1" + resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz#758e959194b90aea0270db18fff75e2fceb2239f" + integrity sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg== dependencies: - fast-decode-uri-component "^1.0.0" + fast-decode-uri-component "^1.0.1" + fast-deep-equal "^3.1.3" safe-regex2 "^2.0.0" semver-store "^0.3.0" @@ -12453,6 +12354,36 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gauge@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz#afba07aa0374a93c6219603b1fb83eaa2264d8f8" + integrity sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw== + dependencies: + ansi-regex "^5.0.1" + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -12708,13 +12639,6 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, gl once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" - integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== - dependencies: - ini "^1.3.5" - global-dirs@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" @@ -12835,17 +12759,17 @@ google-p12-pem@^3.0.3: dependencies: node-forge "^1.0.0" -got@^11.8.0, got@^11.8.2: - version "11.8.2" - resolved "https://registry.npmjs.org/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" - integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== +got@11.8.3, got@^11.8.0: + version "11.8.3" + resolved "https://registry.npmjs.org/got/-/got-11.8.3.tgz#f496c8fdda5d729a90b4905d2b07dbd148170770" + integrity sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg== dependencies: "@sindresorhus/is" "^4.0.0" "@szmarczak/http-timer" "^4.0.5" "@types/cacheable-request" "^6.0.1" "@types/responselike" "^1.0.0" cacheable-lookup "^5.0.3" - cacheable-request "^7.0.1" + cacheable-request "^7.0.2" decompress-response "^6.0.0" http2-wrapper "^1.0.0-beta.5.2" lowercase-keys "^2.0.0" @@ -12869,12 +12793,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6: - version "4.2.6" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" - integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== - -graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.5, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.9" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -13255,10 +13174,10 @@ headers-utils@^3.0.2: resolved "https://registry.npmjs.org/headers-utils/-/headers-utils-3.0.2.tgz#dfc65feae4b0e34357308aefbcafa99c895e59ef" integrity sha512-xAxZkM1dRyGV2Ou5bzMxBPNLoRCjcX+ya7KSWybQD2KwLphxsapUVK6x/02o7f4VU6GPSXch9vNY2+gkU8tYWQ== -helmet@^4.0.0: - version "4.4.1" - resolved "https://registry.npmjs.org/helmet/-/helmet-4.4.1.tgz#a17e1444d81d7a83ddc6e6f9bc6e2055b994efe7" - integrity sha512-G8tp0wUMI7i8wkMk2xLcEvESg5PiCitFMYgGRc/PwULB0RVhTP5GFdxOwvJwp9XVha8CuS8mnhmE8I/8dx/pbw== +helmet@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/helmet/-/helmet-5.0.2.tgz#3264ec6bab96c82deaf65e3403c369424cb2366c" + integrity sha512-QWlwUZZ8BtlvwYVTSDTBChGf8EOcQ2LkGMnQJxSzD1mUu8CCjXJZq/BXP8eWw4kikRnzlhtYo3lCk0ucmYA3Vg== hexoid@1.0.0: version "1.0.0" @@ -13629,6 +13548,11 @@ ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +immer@9.0.7: + version "9.0.7" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz#b6156bd7db55db7abc73fd2fdadf4e579a701075" + integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA== + immer@^9.0.1, immer@^9.0.7: version "9.0.12" resolved "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" @@ -13843,10 +13767,10 @@ interpret@^2.2.0: resolved "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -into-stream@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/into-stream/-/into-stream-5.1.1.tgz#f9a20a348a11f3c13face22763f2d02e127f4db8" - integrity sha512-krrAJ7McQxGGmvaYbB7Q1mcA+cRwg9Ij2RfWIeVesNBgVDZmzY/Fa4IpZUT3bmdRzMzdf/mzltCG2Dq99IZGBA== +into-stream@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz#4bfc1244c0128224e18b8870e85b2de8e66c6702" + integrity sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA== dependencies: from2 "^2.3.0" p-is-promise "^3.0.0" @@ -14156,15 +14080,7 @@ is-in-browser@^1.0.2, is-in-browser@^1.1.3: resolved "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU= -is-installed-globally@^0.3.1: - version "0.3.2" - resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" - integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== - dependencies: - global-dirs "^2.0.1" - is-path-inside "^3.0.1" - -is-installed-globally@~0.4.0: +is-installed-globally@^0.4.0, is-installed-globally@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== @@ -14204,10 +14120,10 @@ is-node-process@^1.0.1: resolved "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23" integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ== -is-npm@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" - integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== +is-npm@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" + integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== is-number-object@^1.0.4: version "1.0.4" @@ -14248,11 +14164,6 @@ is-path-cwd@^2.2.0: resolved "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== -is-path-inside@^3.0.1: - version "3.0.2" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" - integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== - is-path-inside@^3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" @@ -15577,15 +15488,15 @@ jsx-ast-utils@^3.2.1: array-includes "^3.1.3" object.assign "^4.1.2" -just-diff-apply@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-3.0.0.tgz#a77348d24f0694e378b57293dceb65bdf5a91c4f" - integrity sha512-K2MLc+ZC2DVxX4V61bIKPeMUUfj1YYZ3h0myhchDXOW1cKoPZMnjIoNCqv9bF2n5Oob1PFxuR2gVJxkxz4e58w== +just-diff-apply@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-4.0.1.tgz#da89c5a4ccb14aa8873c70e2c3b6695cef45dab5" + integrity sha512-AKOkzB5P6FkfP21UlZVX/OPXx/sC2GagpLX9cBxqHqDuRjwmZ/AJRKSNrB9jHPpRW1W1ONs6gly1gW46t055nQ== -just-diff@^3.0.1: - version "3.1.1" - resolved "https://registry.npmjs.org/just-diff/-/just-diff-3.1.1.tgz#d50c597c6fd4776495308c63bdee1b6839082647" - integrity sha512-sdMWKjRq8qWZEjDcVA6llnUT8RDEBIfOiGpYFPYa9u+2c39JCsejktSP7mj5eRid5EIvTzIpQ2kDOCw1Nq9BjQ== +just-diff@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/just-diff/-/just-diff-5.0.1.tgz#db8fe1cfeea1156f2374bfb289826dca28e7e390" + integrity sha512-X00TokkRIDotUIf3EV4xUm6ELc/IkqhS/vPSHdWnsM5y0HoNMfEqrazizI7g78lpHvnRSRt/PFfKtRqJCOGIuQ== just-extend@^4.0.2: version "4.2.1" @@ -15728,7 +15639,7 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" -latest-version@5.1.0, latest-version@^5.0.0: +latest-version@5.1.0, latest-version@^5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== @@ -15762,9 +15673,9 @@ ldap-filter@^0.3.3: assert-plus "^1.0.0" ldapjs@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.0.tgz#999c85f642216709009dc8728e58ac7793888def" - integrity sha512-3Rbm3CS7vzTccpP1QnzKCEPok60L/b3BFlWU8r93P5oadCAaqCWEH9Td08crPnw4Ti20W8y0+ZKtFFNzxVu4kA== + version "2.3.1" + resolved "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.1.tgz#04136815fb1f21d692ac87fab5961a04d86e8b04" + integrity sha512-kf0tHHLrpwKaBAQOhYHXgdeh2PkFuCCxWgLb1MRn67ZQVo787D2pij3mmHVZx193GIdM8xcfi8HF6AIYYnj0fQ== dependencies: abstract-logging "^2.0.0" asn1 "^0.2.4" @@ -16387,6 +16298,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@^7.3.1: + version "7.3.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.3.1.tgz#7702e80694ec2bf19865567a469f2b081fcf53f5" + integrity sha512-nX1x4qUrKqwbIAhv4s9et4FIUVzNOpeY07bsjGUy8gwJrXH/wScImSQqXErmo/b2jZY2r0mohbLA9zVj7u1cNw== + lru-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -16399,15 +16315,10 @@ lunr@^2.3.9: resolved "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== -luxon@2.0.2, luxon@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/luxon/-/luxon-2.0.2.tgz#11f2cd4a11655fdf92e076b5782d7ede5bcdd133" - integrity sha512-ZRioYLCgRHrtTORaZX1mx+jtxKtKuI5ZDvHNAmqpUzGqSrR+tL4FVLn/CUGMA3h0+AKD1MAxGI5GnCqR5txNqg== - -luxon@^1.27.0: - version "1.28.0" - resolved "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz#e7f96daad3938c06a62de0fb027115d251251fbf" - integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ== +luxon@^2.0.2: + version "2.3.0" + resolved "https://registry.npmjs.org/luxon/-/luxon-2.3.0.tgz#bf16a7e642513c2a20a6230a6a41b0ab446d0045" + integrity sha512-gv6jZCV+gGIrVKhO90yrsn8qXPKD8HYZJtrUDSfEbow8Tkw84T9OnCyJhWvnJIaIF/tBuiAjZuQHUt1LddX2mg== lz-string@^1.4.4: version "1.4.4" @@ -16453,6 +16364,28 @@ make-error@^1, make-error@^1.1.1, make-error@^1.3.6: resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +make-fetch-happen@^10.0.1: + version "10.0.2" + resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.0.2.tgz#0afb38d2f951b17ebc482b0b16c8d77f39dfe389" + integrity sha512-JSFLK53NJP22FL/eAGOyKsWbc2G3v+toPMD7Dq9PJKQCvK0i3t8hGkKxe+3YZzwYa+c0kxRHu7uxH3fvO+rsaA== + dependencies: + agentkeepalive "^4.2.0" + cacache "^15.3.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^7.3.1" + minipass "^3.1.6" + minipass-collect "^1.0.2" + minipass-fetch "^1.4.1" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.3" + promise-retry "^2.0.1" + socks-proxy-agent "^6.1.1" + ssri "^8.0.1" + make-fetch-happen@^8.0.9: version "8.0.14" resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz#aaba73ae0ab5586ad8eaa68bd83332669393e222" @@ -16474,7 +16407,7 @@ make-fetch-happen@^8.0.9: socks-proxy-agent "^5.0.0" ssri "^8.0.0" -make-fetch-happen@^9.0.1: +make-fetch-happen@^9.1.0: version "9.1.0" resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== @@ -16702,11 +16635,6 @@ mdn-data@2.0.14: resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - mdurl@^1.0.0, mdurl@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" @@ -17181,7 +17109,7 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.34" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== @@ -17246,9 +17174,9 @@ min-indent@^1.0.0: integrity sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY= mini-css-extract-plugin@^2.4.2: - version "2.5.2" - resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.2.tgz#b3b9b98320c2c054d92c16f6a94ddfdbbba13755" - integrity sha512-Lwgq9qLNyBK6yNLgzssXnq4r2+mB9Mz3cJWlM8kseysHIvTicFhDNimFgY94jjqlwhNzLPsq8wv4X+vOHtMdYA== + version "2.5.3" + resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.5.3.tgz#c5c79f9b22ce9b4f164e9492267358dbe35376d9" + integrity sha512-YseMB8cs8U/KCaAGQoqYmfUuhhGW0a9p9XvWXrxVOkE3/IiISTLw4ALNt7JR5B2eYauFM+PQGSbXMDmVbR7Tfw== dependencies: schema-utils "^4.0.0" @@ -17297,10 +17225,10 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: - version "1.3.3" - resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz#34c7cea038c817a8658461bf35174551dce17a0a" - integrity sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ== +minipass-fetch@^1.3.0, minipass-fetch@^1.3.2, minipass-fetch@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== dependencies: minipass "^3.1.0" minipass-sized "^1.0.3" @@ -17345,10 +17273,10 @@ minipass@^2.6.0, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" -minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6: + version "3.1.6" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== dependencies: yallist "^4.0.0" @@ -17359,7 +17287,7 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -minizlib@^2.0.0, minizlib@^2.1.1: +minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -17394,7 +17322,7 @@ mkdirp-infer-owner@^2.0.0: infer-owner "^1.0.4" mkdirp "^1.0.3" -"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -17575,11 +17503,6 @@ named-placeholders@^1.1.2: dependencies: lru-cache "^4.1.3" -nan@^2.14.0: - version "2.14.1" - resolved "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== - nan@^2.14.1, nan@^2.15.0: version "2.15.0" resolved "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" @@ -17604,11 +17527,16 @@ nanoclone@^0.2.1: resolved "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanoid@^3.1.23, nanoid@^3.1.30: +nanoid@^3.1.23: version "3.2.0" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== +nanoid@^3.2.0: + version "3.3.0" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.0.tgz#5906f776fd886c66c24f3653e0c46fcb1d4ad6b0" + integrity sha512-JzxqqT5u/x+/KOFSd7JP15DOo9nOoHpx6DYatqIHUW2+flybkm+mdcraotSQR5WcnZr+qhGVh8Ted0KdfSMxlg== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -17631,7 +17559,12 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@0.6.2, negotiator@^0.6.2: +negotiator@0.6.3, negotiator@^0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +negotiator@^0.6.2: version "0.6.2" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== @@ -17716,13 +17649,6 @@ node-fetch@2.6.1: resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@2.6.5: - version "2.6.5" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" - integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== - dependencies: - whatwg-url "^5.0.0" - node-fetch@2.6.7, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.5, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -17768,6 +17694,22 @@ node-gyp@^7.1.0: tar "^6.0.2" which "^2.0.2" +node-gyp@^8.2.0: + version "8.4.1" + resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -17830,20 +17772,20 @@ node-releases@^2.0.1: integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== nodemon@^2.0.2: - version "2.0.12" - resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz#5dae4e162b617b91f1873b3bfea215dd71e144d5" - integrity sha512-egCTmNZdObdBxUBw6ZNwvZ/xzk24CKRs5K6d+5zbmrMr7rOpPmfPeF6OxM3DDpaRx331CQRFEktn+wrFFfBSOA== + version "2.0.15" + resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e" + integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA== dependencies: - chokidar "^3.2.2" - debug "^3.2.6" + chokidar "^3.5.2" + debug "^3.2.7" ignore-by-default "^1.0.1" minimatch "^3.0.4" - pstree.remy "^1.1.7" + pstree.remy "^1.1.8" semver "^5.7.1" supports-color "^5.5.0" touch "^3.1.0" - undefsafe "^2.0.3" - update-notifier "^4.1.0" + undefsafe "^2.0.5" + update-notifier "^5.1.0" nopt@^4.0.1: version "4.0.3" @@ -18004,17 +17946,17 @@ npm-pick-manifest@^6.1.0, npm-pick-manifest@^6.1.1: npm-package-arg "^8.1.2" semver "^7.3.4" -npm-registry-fetch@^11.0.0: - version "11.0.0" - resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz#68c1bb810c46542760d62a6a965f85a702d43a76" - integrity sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA== +npm-registry-fetch@^12.0.0, npm-registry-fetch@^12.0.1: + version "12.0.2" + resolved "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-12.0.2.tgz#ae583bb3c902a60dae43675b5e33b5b1f6159f1e" + integrity sha512-Df5QT3RaJnXYuOwtXBXS9BWs+tHH2olvkCLh6jcR/b/u3DvPMlp3J0TvvYwplPKxHMOwfg287PYih9QqaVFoKA== dependencies: - make-fetch-happen "^9.0.1" - minipass "^3.1.3" - minipass-fetch "^1.3.0" + make-fetch-happen "^10.0.1" + minipass "^3.1.6" + minipass-fetch "^1.4.1" minipass-json-stream "^1.0.1" - minizlib "^2.0.0" - npm-package-arg "^8.0.0" + minizlib "^2.1.2" + npm-package-arg "^8.1.5" npm-registry-fetch@^9.0.0: version "9.0.0" @@ -18054,12 +17996,25 @@ npmlog@^4.1.2: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== dependencies: - boolbase "~1.0.0" + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +npmlog@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17" + integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.0" + set-blocking "^2.0.0" nth-check@^2.0.0: version "2.0.1" @@ -18171,7 +18126,7 @@ object.fromentries@^2.0.5: define-properties "^1.1.3" es-abstract "^1.19.1" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: +object.getownpropertydescriptors@^2.0.3: version "2.1.0" resolved "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== @@ -18194,7 +18149,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0, object.values@^1.1.5: +object.values@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== @@ -18532,6 +18487,14 @@ p-timeout@^3.2.0: dependencies: p-finally "^1.0.0" +p-transform@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/p-transform/-/p-transform-1.3.0.tgz#2da960ba92c6a56efbe75cbd1edf3ea7b3191049" + integrity sha512-UJKdSzgd3KOnXXAtqN5+/eeHcvTn1hBkesEmElVgvO/NAYcxAvmjzIGmnNd3Tb/gRAvMBdNRFD4qAWdHxY6QXg== + dependencies: + debug "^4.3.2" + p-queue "^6.6.2" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -18564,31 +18527,6 @@ packet-reader@1.0.0: resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== -pacote@^11.1.11, pacote@^11.3.5: - version "11.3.5" - resolved "https://registry.npmjs.org/pacote/-/pacote-11.3.5.tgz#73cf1fc3772b533f575e39efa96c50be8c3dc9d2" - integrity sha512-fT375Yczn4zi+6Hkk2TBe1x1sP8FgFsEIZ2/iWaXY2r/NkhDJfxbcn5paz1+RTFCyNf+dPnaoBDJoAxXSU8Bkg== - dependencies: - "@npmcli/git" "^2.1.0" - "@npmcli/installed-package-contents" "^1.0.6" - "@npmcli/promise-spawn" "^1.2.0" - "@npmcli/run-script" "^1.8.2" - cacache "^15.0.5" - chownr "^2.0.0" - fs-minipass "^2.1.0" - infer-owner "^1.0.4" - minipass "^3.1.3" - mkdirp "^1.0.3" - npm-package-arg "^8.0.1" - npm-packlist "^2.1.4" - npm-pick-manifest "^6.0.0" - npm-registry-fetch "^11.0.0" - promise-retry "^2.0.1" - read-package-json-fast "^2.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.1.0" - pacote@^11.2.6: version "11.2.6" resolved "https://registry.npmjs.org/pacote/-/pacote-11.2.6.tgz#c0426e5d5c8d33aeea3461a75e1390f1ba78f953" @@ -18614,6 +18552,31 @@ pacote@^11.2.6: ssri "^8.0.1" tar "^6.1.0" +pacote@^12.0.0, pacote@^12.0.2: + version "12.0.3" + resolved "https://registry.npmjs.org/pacote/-/pacote-12.0.3.tgz#b6f25868deb810e7e0ddf001be88da2bcaca57c7" + integrity sha512-CdYEl03JDrRO3x18uHjBYA9TyoW8gy+ThVcypcDkxPtKlw76e4ejhYB6i9lJ+/cebbjpqPW/CijjqxwDTts8Ow== + dependencies: + "@npmcli/git" "^2.1.0" + "@npmcli/installed-package-contents" "^1.0.6" + "@npmcli/promise-spawn" "^1.2.0" + "@npmcli/run-script" "^2.0.0" + cacache "^15.0.5" + chownr "^2.0.0" + fs-minipass "^2.1.0" + infer-owner "^1.0.4" + minipass "^3.1.3" + mkdirp "^1.0.3" + npm-package-arg "^8.0.1" + npm-packlist "^3.0.0" + npm-pick-manifest "^6.0.0" + npm-registry-fetch "^12.0.0" + promise-retry "^2.0.1" + read-package-json-fast "^2.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.1.0" + pako@^1.0.10, pako@~1.0.5: version "1.0.11" resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -18651,14 +18614,14 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-conflict-json@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz#54ec175bde0f2d70abf6be79e0e042290b86701b" - integrity sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw== +parse-conflict-json@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-2.0.1.tgz#76647dd072e6068bcaff20be6ccea68a18e1fb58" + integrity sha512-Y7nYw+QaSGBto1LB9lgwOR05Rtz5SbuTf+Oe7HJ6SYQ/DHsvRjQ8O03oWdJbvkt6GzDWospgyZbGmjDYL0sDgA== dependencies: - json-parse-even-better-errors "^2.3.0" - just-diff "^3.0.1" - just-diff-apply "^3.0.0" + json-parse-even-better-errors "^2.3.1" + just-diff "^5.0.1" + just-diff-apply "^4.0.1" parse-entities@^2.0.0: version "2.0.0" @@ -18824,7 +18787,7 @@ passport-oauth2@1.2.0: passport-strategy "1.x.x" uid2 "0.0.x" -passport-oauth2@1.x.x, passport-oauth2@^1.1.2, passport-oauth2@^1.4.0, passport-oauth2@^1.5.0: +passport-oauth2@1.x.x, passport-oauth2@^1.1.2, passport-oauth2@^1.4.0, passport-oauth2@^1.6.1: version "1.6.1" resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b" integrity sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ== @@ -19045,10 +19008,10 @@ pg-int8@1.0.1: resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.4.1: - version "3.4.1" - resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz#0e71ce2c67b442a5e862a9c182172c37eda71e9c" - integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ== +pg-pool@^3.5.1: + version "3.5.1" + resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.1.tgz#f499ce76f9bf5097488b3b83b19861f28e4ed905" + integrity sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ== pg-protocol@^1.5.0: version "1.5.0" @@ -19067,14 +19030,14 @@ pg-types@^2.1.0: postgres-interval "^1.1.0" pg@^8.3.0, pg@^8.4.0: - version "8.7.1" - resolved "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz#9ea9d1ec225980c36f94e181d009ab9f4ce4c471" - integrity sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA== + version "8.7.3" + resolved "https://registry.npmjs.org/pg/-/pg-8.7.3.tgz#8a5bdd664ca4fda4db7997ec634c6e5455b27c44" + integrity sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" pg-connection-string "^2.5.0" - pg-pool "^3.4.1" + pg-pool "^3.5.1" pg-protocol "^1.5.0" pg-types "^2.1.0" pgpass "1.x" @@ -19511,19 +19474,19 @@ postcss-value-parser@^3.3.0: resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== +postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8, postcss@^8.1.0, postcss@^8.2.15: - version "8.4.5" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== +postcss@^8.1.0, postcss@^8.4.5: + version "8.4.6" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1" + integrity sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA== dependencies: - nanoid "^3.1.30" + nanoid "^3.2.0" picocolors "^1.0.0" - source-map-js "^1.0.1" + source-map-js "^1.0.2" postgres-array@~2.0.0: version "2.0.0" @@ -19816,10 +19779,10 @@ psl@^1.1.28, psl@^1.1.33: resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== -pstree.remy@^1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.7.tgz#c76963a28047ed61542dc361aa26ee55a7fa15f3" - integrity sha512-xsMgrUwRpuGskEzBFkH8NmTimbZ5PcPup0LA8JJkHIm2IMUbQcpo3yeLNWVrufEYjh8YwtSVh0xz6UeWc5Oh5A== +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== public-encrypt@^4.0.0: version "4.0.3" @@ -19870,32 +19833,32 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -pupa@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" - integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== +pupa@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== dependencies: escape-goat "^2.0.0" puppeteer@^13.1.1: - version "13.1.1" - resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-13.1.1.tgz#63771eb744202aa91918c49123f846e1747da121" - integrity sha512-GwdFy1JQ43Hhxj6MraXme+XfCX2CKe18MuwToXTMEAk0txg6vUEgwqBnzErTTqDVZ7sWYrDtDaRCfD2y7ZwgGw== + version "13.3.2" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-13.3.2.tgz#4ff1cf6e2009df29fd80038bc702dc067776f79d" + integrity sha512-TIt8/R0eaUwY1c0/O0sCJpSglvGEWVoWFfGZ2dNtxX3eHuBo1ln9abaWfxTjZfsrkYATLSs8oqEdRZpMNnCsvg== dependencies: - debug "4.3.2" - devtools-protocol "0.0.948846" + cross-fetch "3.1.5" + debug "4.3.3" + devtools-protocol "0.0.960912" extract-zip "2.0.1" https-proxy-agent "5.0.0" - node-fetch "2.6.5" pkg-dir "4.2.0" progress "2.0.3" proxy-from-env "1.1.0" rimraf "3.0.2" tar-fs "2.1.1" unbzip2-stream "1.4.3" - ws "8.2.3" + ws "8.5.0" -q@^1.1.2, q@^1.5.1: +q@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= @@ -19905,10 +19868,10 @@ qs@6.9.3: resolved "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e" integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw== -qs@6.9.6: - version "6.9.6" - resolved "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== +qs@6.9.7: + version "6.9.7" + resolved "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" + integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== qs@^6.10.1, qs@^6.10.2, qs@^6.9.1, qs@^6.9.4, qs@^6.9.6: version "6.10.3" @@ -20014,7 +19977,17 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.2, raw-body@^2.4.1: +raw-body@2.4.3: + version "2.4.3" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" + integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== + dependencies: + bytes "3.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@^2.4.1: version "2.4.2" resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== @@ -20394,7 +20367,7 @@ react-use@^17.2.4: ts-easing "^0.2.0" tslib "^2.1.0" -react-use@^17.3.1: +react-use@^17.3.1, react-use@^17.3.2: version "17.3.2" resolved "https://registry.npmjs.org/react-use/-/react-use-17.3.2.tgz#448abf515f47c41c32455024db28167cb6e53be8" integrity sha512-bj7OD0/1wL03KyWmzFXAFe425zziuTf7q8olwCYBfOeFHY1qfO1FAMjROQLsLZYwG4Rx63xAfb7XAbBrJsZmEw== @@ -21286,7 +21259,7 @@ rollup-plugin-peer-deps-external@^2.2.2: 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@^4.0.0: +rollup-plugin-postcss@*, rollup-plugin-postcss@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz#15e9462f39475059b368ce0e49c800fa4b1f7050" integrity sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w== @@ -21321,9 +21294,9 @@ rollup@^0.63.4: "@types/node" "*" rollup@^2.60.2: - version "2.60.2" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.60.2.tgz#3f45ace36a9b10b4297181831ea0719922513463" - integrity sha512-1Bgjpq61sPjgoZzuiDSGvbI1tD91giZABgjCQBKM5aYLnzjq52GoDuWVwT/cm/MCxCMPU8gqQvkj8doQ5C8Oqw== + version "2.67.2" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.67.2.tgz#d95e15f60932ad21e05a870bd0aa0b235d056f04" + integrity sha512-hoEiBWwZtf1QdK3jZIq59L0FJj4Fiv4RplCO4pvCRC86qsoFurWB4hKQIjoRf3WvJmk5UZ9b0y5ton+62fC7Tw== optionalDependencies: fsevents "~2.3.2" @@ -21441,7 +21414,7 @@ sax@1.2.1: resolved "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= -sax@>=0.6.0, sax@~1.2.4: +sax@>=0.6.0: version "1.2.4" resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -21453,7 +21426,7 @@ saxes@^5.0.0, saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -scheduler@^0.19.0, scheduler@^0.19.1: +scheduler@^0.19.1: version "0.19.1" resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== @@ -21767,10 +21740,10 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== signedsource@^1.0.0: version "1.0.0" @@ -21938,10 +21911,10 @@ socks-proxy-agent@^5.0.0: debug "4" socks "^2.3.3" -socks-proxy-agent@^6.0.0: - version "6.1.0" - resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz#869cf2d7bd10fea96c7ad3111e81726855e285c3" - integrity sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg== +socks-proxy-agent@^6.0.0, socks-proxy-agent@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" + integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== dependencies: agent-base "^6.0.2" debug "^4.3.1" @@ -21990,10 +21963,10 @@ source-list-map@^2.0.1: resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" - integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-resolve@^0.5.0: version "0.5.3" @@ -22401,7 +22374,16 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.1: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -22418,15 +22400,6 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.0: version "5.1.0" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.0.tgz#5ab00980cfb29f43e736b113a120a73a0fb569d3" @@ -22739,25 +22712,6 @@ svg-parser@^2.0.2: resolved "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^1.2.2: - version "1.3.2" - resolved "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - svgo@^2.5.0, svgo@^2.7.0: version "2.8.0" resolved "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" @@ -22838,9 +22792,9 @@ swap-case@^2.0.2: tslib "^2.0.3" swr@^1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/swr/-/swr-1.1.2.tgz#9f3de2541931fccf03c48f322f1fc935a7551612" - integrity sha512-UsM0eo5T+kRPyWFZtWRx2XR5qzohs/LS4lDC0GCyLpCYFmsfTk28UCVDbOE9+KtoXY4FnwHYiF+ZYEU3hnJ1lQ== + version "1.2.1" + resolved "https://registry.npmjs.org/swr/-/swr-1.2.1.tgz#c21a4fe2139cb1c4630450589b5b5add947a9d41" + integrity sha512-1cuWXqJqXcFwbgONGCY4PHZ8v05009JdHsC3CIC6u7d00kgbMswNr1sHnnhseOBxtzVqcCNpOHEgVDciRer45w== symbol-observable@1.2.0, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" @@ -22947,20 +22901,20 @@ tdigest@^0.1.1: bintrees "1.0.1" "techdocs-cli-embedded-app@link:packages/techdocs-cli-embedded-app": - version "0.2.63" + version "0.2.64" dependencies: - "@backstage/app-defaults" "^0.1.7" - "@backstage/catalog-model" "^0.9.10" - "@backstage/cli" "^0.13.2" - "@backstage/config" "^0.1.13" - "@backstage/core-app-api" "^0.5.2" - "@backstage/core-components" "^0.8.8" - "@backstage/core-plugin-api" "^0.6.0" - "@backstage/integration-react" "^0.1.21" - "@backstage/plugin-catalog" "^0.7.12" - "@backstage/plugin-techdocs" "^0.13.3" - "@backstage/test-utils" "^0.2.4" - "@backstage/theme" "^0.2.14" + "@backstage/app-defaults" "^0.1.8" + "@backstage/catalog-model" "^0.10.0" + "@backstage/cli" "^0.14.0" + "@backstage/config" "^0.1.14" + "@backstage/core-app-api" "^0.5.3" + "@backstage/core-components" "^0.8.9" + "@backstage/core-plugin-api" "^0.6.1" + "@backstage/integration-react" "^0.1.22" + "@backstage/plugin-catalog" "^0.8.0" + "@backstage/plugin-techdocs" "^0.13.4" + "@backstage/test-utils" "^0.2.5" + "@backstage/theme" "^0.2.15" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" history "^5.0.0" @@ -23706,12 +23660,10 @@ unc-path-regex@^0.1.2: resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= -undefsafe@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" - integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== - dependencies: - debug "^2.2.0" +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== underscore@^1.12.1, underscore@^1.9.1: version "1.13.1" @@ -23905,11 +23857,6 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -23944,22 +23891,23 @@ upath@^2.0.1: resolved "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b" integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w== -update-notifier@^4.1.0: - version "4.1.3" - resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" - integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== +update-notifier@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9" + integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw== dependencies: - boxen "^4.2.0" - chalk "^3.0.0" + boxen "^5.0.0" + chalk "^4.1.0" configstore "^5.0.1" has-yarn "^2.1.0" import-lazy "^2.1.0" is-ci "^2.0.0" - is-installed-globally "^0.3.1" - is-npm "^4.0.0" + is-installed-globally "^0.4.0" + is-npm "^5.0.0" is-yarn-global "^0.3.0" - latest-version "^5.0.0" - pupa "^2.0.1" + latest-version "^5.1.0" + pupa "^2.1.1" + semver "^7.3.4" semver-diff "^3.1.1" xdg-basedir "^4.0.0" @@ -23997,9 +23945,9 @@ url-parse-lax@^3.0.0: prepend-http "^2.0.0" url-parse@^1.5.3: - version "1.5.3" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" - integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== + version "1.5.7" + resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.7.tgz#00780f60dbdae90181f51ed85fb24109422c932a" + integrity sha512-HxWkieX+STA38EDk7CE9MEryFeHCKzgagxlGvsdS7WBImq9Mk+PGwiT56w82WI3aicwJA8REp42Cxo98c8FZMA== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" @@ -24059,16 +24007,6 @@ util-promisify@^2.1.0: dependencies: object.getownpropertydescriptors "^2.0.3" -util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" - util@0.10.3: version "0.10.3" resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" @@ -24282,9 +24220,9 @@ vm-browserify@^1.0.1: integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vm2@^3.9.6: - version "3.9.6" - resolved "https://registry.npmjs.org/vm2/-/vm2-3.9.6.tgz#2f9b2fd0d82802dcd872e1011869ba8ae6b74778" - integrity sha512-BF7euUjgO+ezsz2UKex9kO9M/PtDNOf+KEpiqNepZsgf1MT7JYfJEIvG8BoYhZMLAVjqevFJ0UmXNuETe8m5dQ== + version "3.9.7" + resolved "https://registry.npmjs.org/vm2/-/vm2-3.9.7.tgz#bb87aa677c97c61e23a6cb6547e44e990517a6f6" + integrity sha512-g/GZ7V0Mlmch3eDVOATvAXr1GsJNg6kQ5PjvYy3HbJMCRn5slNbo/u73Uy7r5yUej1cRa3ZjtoVwcWSQuQ/fow== dependencies: acorn "^8.7.0" acorn-walk "^8.2.0" @@ -24448,12 +24386,12 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5, webpack@^5.66.0: - version "5.67.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-5.67.0.tgz#cb43ca2aad5f7cc81c4cd36b626e6b819805dbfd" - integrity sha512-LjFbfMh89xBDpUMgA1W9Ur6Rn/gnr2Cq1jjHFPo4v6a79/ypznSYbAyPgGhwsxBtMIaEmDD1oJoA7BEYw/Fbrw== + version "5.69.1" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.69.1.tgz#8cfd92c192c6a52c99ab00529b5a0d33aa848dc5" + integrity sha512-+VyvOSJXZMT2V5vLzOnDuMz5GxEqLk7hKWQ56YxPW/PQRUuKimPqmEIJOx8jHYeyo65pKbapbW464mvsKbaj4A== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" @@ -24599,12 +24537,12 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +wide-align@^1.1.0, wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: - string-width "^1.0.2 || 2" + string-width "^1.0.2 || 2 || 3 || 4" widest-line@^3.1.0: version "3.1.0" @@ -24718,6 +24656,14 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write-file-atomic@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz#9faa33a964c1c85ff6f849b80b42a88c2c537c8f" + integrity sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + write-json-file@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" @@ -24756,20 +24702,15 @@ ws@7.4.5: resolved "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1" integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== -ws@8.2.3: - version "8.2.3" - resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== - ws@8.3.0, "ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.2.3, ws@^7.3.1, ws@^7.4.6, ws@^8.3.0: version "7.5.6" resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== -ws@^8.1.0: - version "8.4.2" - resolved "https://registry.npmjs.org/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" - integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== +ws@8.5.0, ws@^8.1.0: + version "8.5.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== xcase@^2.0.1: version "2.0.1" @@ -25015,13 +24956,13 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yeoman-environment@^3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-3.6.0.tgz#91267ced0d474c4dec330b83f232e72e796c0730" - integrity sha512-X16N9lhzRdUKFT8MZrpwjLDKsdgAUqh4VPR2wAXeAqjJJaUxYBxCQGFxtZVTf3vbyNuIHXPunwOLtK60bpapbg== +yeoman-environment@^3.9.1: + version "3.9.1" + resolved "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-3.9.1.tgz#21912bdee4b1d302a5c25a7d31338fa092ea7116" + integrity sha512-IdRnbQt/DSOSnao0oD9c+or1X2UrL+fx9eC0O7Lq/MGZV68nhv9k77MqG+hEAySPSlyCpocVlhfQwV62hczk5Q== dependencies: - "@npmcli/arborist" "^2.2.2" - are-we-there-yet "^1.1.5" + "@npmcli/arborist" "^4.0.4" + are-we-there-yet "^2.0.0" arrify "^2.0.1" binaryextensions "^4.15.0" chalk "^4.1.0" @@ -25043,9 +24984,10 @@ yeoman-environment@^3.6.0: mem-fs "^1.2.0 || ^2.0.0" mem-fs-editor "^8.1.2 || ^9.0.0" minimatch "^3.0.4" - npmlog "^4.1.2" + npmlog "^5.0.1" p-queue "^6.6.2" - pacote "^11.2.6" + p-transform "^1.3.0" + pacote "^12.0.2" preferred-pm "^3.0.3" pretty-bytes "^5.3.0" semver "^7.1.3" @@ -25126,6 +25068,11 @@ zod@^3.11.6, zod@^3.9.5: resolved "https://registry.npmjs.org/zod/-/zod-3.11.6.tgz#e43a5e0c213ae2e02aefe7cb2b1a6fa3d7f1f483" integrity sha512-daZ80A81I3/9lIydI44motWe6n59kRBfNzTuS2bfzVh1nAXi667TOTWWtatxyG+fwgNUiagSj/CWZwRRbevJIg== +zustand@3.6.9: + version "3.6.9" + resolved "https://registry.npmjs.org/zustand/-/zustand-3.6.9.tgz#f61a756ddea9f95c7ee7cfd3af2f88c10078afbc" + integrity sha512-OvDNu/jEWpRnEC7k8xh8GKjqYog7td6FZrLMuHs/IeI8WhrCwV+FngVuwMIFhp5kysZXr6emaeReMqjLGaldAQ== + zwitch@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1"