diff --git a/.changeset/afraid-planets-crash.md b/.changeset/afraid-planets-crash.md new file mode 100644 index 0000000000..b31a492f3d --- /dev/null +++ b/.changeset/afraid-planets-crash.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. diff --git a/.changeset/brave-lemons-chew.md b/.changeset/brave-lemons-chew.md new file mode 100644 index 0000000000..61bf7cc6af --- /dev/null +++ b/.changeset/brave-lemons-chew.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-catalog-backend': patch +--- + +Minor improvements to the descriptions provided with permission rules schemas diff --git a/.changeset/breezy-ears-rule.md b/.changeset/breezy-ears-rule.md new file mode 100644 index 0000000000..753554187d --- /dev/null +++ b/.changeset/breezy-ears-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-gitlab': patch +--- + +The config now consistently uses the term 'instance' to refer to a single GitLab API host. diff --git a/.changeset/bright-plums-cough.md b/.changeset/bright-plums-cough.md new file mode 100644 index 0000000000..9af30f002e --- /dev/null +++ b/.changeset/bright-plums-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. diff --git a/.changeset/bright-teachers-compete.md b/.changeset/bright-teachers-compete.md new file mode 100644 index 0000000000..3cc900d613 --- /dev/null +++ b/.changeset/bright-teachers-compete.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. diff --git a/.changeset/brown-kings-wait.md b/.changeset/brown-kings-wait.md new file mode 100644 index 0000000000..db3fc0ee86 --- /dev/null +++ b/.changeset/brown-kings-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +The list of entities takes into account the title when its different from the name to sort the entities. diff --git a/.changeset/chatty-lemons-reply.md b/.changeset/chatty-lemons-reply.md new file mode 100644 index 0000000000..118f832646 --- /dev/null +++ b/.changeset/chatty-lemons-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Export `decodeElasticSearchPageCursor` utility function diff --git a/.changeset/chilled-brooms-jog.md b/.changeset/chilled-brooms-jog.md new file mode 100644 index 0000000000..d848246b2b --- /dev/null +++ b/.changeset/chilled-brooms-jog.md @@ -0,0 +1,7 @@ +--- +'@backstage/backend-common': patch +--- + +**BREAKING**: The `CacheClient` interface must now also implement the `withOptions` method. The `.get()` method has also received a type parameter that helps ensure that `undefined` in the event of a cache miss is handled. + +Added a `cacheToPluginCacheManager` helper that converts a `CacheService` into a legacy `PluginCacheManager` instance. diff --git a/.changeset/chilled-sheep-collect.md b/.changeset/chilled-sheep-collect.md new file mode 100644 index 0000000000..b944685e16 --- /dev/null +++ b/.changeset/chilled-sheep-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Removed unnecessary `@backstage/cli` dependency. diff --git a/.changeset/cool-spoons-bathe.md b/.changeset/cool-spoons-bathe.md new file mode 100644 index 0000000000..b6bcaf89aa --- /dev/null +++ b/.changeset/cool-spoons-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-lighthouse-backend': minor +--- + +Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits diff --git a/.changeset/dull-fishes-suffer.md b/.changeset/dull-fishes-suffer.md new file mode 100644 index 0000000000..54baae404e --- /dev/null +++ b/.changeset/dull-fishes-suffer.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +Removed the unused `TypesToServiceRef` type diff --git a/.changeset/dull-pianos-shave.md b/.changeset/dull-pianos-shave.md new file mode 100644 index 0000000000..8fae999bda --- /dev/null +++ b/.changeset/dull-pianos-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added aria labels on the support button and sidebar diff --git a/.changeset/eight-vans-drum.md b/.changeset/eight-vans-drum.md new file mode 100644 index 0000000000..8e815a1701 --- /dev/null +++ b/.changeset/eight-vans-drum.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-lighthouse-common': minor +--- + +Introduce @backstage/plugin-lighthouse-common with the API implementation diff --git a/.changeset/eighty-knives-repeat.md b/.changeset/eighty-knives-repeat.md new file mode 100644 index 0000000000..3e32a3589d --- /dev/null +++ b/.changeset/eighty-knives-repeat.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-app-api': patch +'@backstage/backend-common': patch +--- + +Updated to match the new `CacheService` interface. diff --git a/.changeset/eleven-shoes-crash.md b/.changeset/eleven-shoes-crash.md new file mode 100644 index 0000000000..8013f311d5 --- /dev/null +++ b/.changeset/eleven-shoes-crash.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +--- + +scaffolder/next: Implementing a simple `OngoingTask` page diff --git a/.changeset/few-meals-buy.md b/.changeset/few-meals-buy.md new file mode 100644 index 0000000000..c49eb8c7ac --- /dev/null +++ b/.changeset/few-meals-buy.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-aws': patch +--- + +Update to import `LocationSpec` from the correct package. diff --git a/.changeset/few-moons-accept.md b/.changeset/few-moons-accept.md new file mode 100644 index 0000000000..c790e837c8 --- /dev/null +++ b/.changeset/few-moons-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. diff --git a/.changeset/few-trees-cross.md b/.changeset/few-trees-cross.md new file mode 100644 index 0000000000..ed70c3bddb --- /dev/null +++ b/.changeset/few-trees-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed Webpack loader patterns so that they properly match the file suffix only. diff --git a/.changeset/four-tables-fix.md b/.changeset/four-tables-fix.md new file mode 100644 index 0000000000..f17f57e253 --- /dev/null +++ b/.changeset/four-tables-fix.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Added explicit return type signature for `mockServices.config()`. diff --git a/.changeset/friendly-chefs-rule.md b/.changeset/friendly-chefs-rule.md new file mode 100644 index 0000000000..872a36b5ae --- /dev/null +++ b/.changeset/friendly-chefs-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Removing extra imports for `run` script as `TestBackend` auto loads the default factories diff --git a/.changeset/great-goats-talk.md b/.changeset/great-goats-talk.md new file mode 100644 index 0000000000..92a1cd59ee --- /dev/null +++ b/.changeset/great-goats-talk.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': minor +--- + +Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. diff --git a/.changeset/green-adults-retire.md b/.changeset/green-adults-retire.md new file mode 100644 index 0000000000..c13e8d664f --- /dev/null +++ b/.changeset/green-adults-retire.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-dev-utils': minor +--- + +Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. diff --git a/.changeset/green-guests-flow.md b/.changeset/green-guests-flow.md new file mode 100644 index 0000000000..688ff17dd9 --- /dev/null +++ b/.changeset/green-guests-flow.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +--- + +Updated usage of the lifecycle service. diff --git a/.changeset/grumpy-fireants-drop.md b/.changeset/grumpy-fireants-drop.md new file mode 100644 index 0000000000..92b08663f4 --- /dev/null +++ b/.changeset/grumpy-fireants-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/codemods': patch +--- + +Moved `commander` to being a regular dependency. diff --git a/.changeset/hip-chairs-double.md b/.changeset/hip-chairs-double.md new file mode 100644 index 0000000000..e2b03f2e66 --- /dev/null +++ b/.changeset/hip-chairs-double.md @@ -0,0 +1,19 @@ +--- +'@backstage/plugin-tech-radar': patch +--- + +Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + +```diff +- url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ ++ { ++ url: 'https://www.javascript.com/', ++ title: 'Learn more', ++ }, + ], +``` diff --git a/.changeset/hip-onions-tan.md b/.changeset/hip-onions-tan.md new file mode 100644 index 0000000000..01be0d4867 --- /dev/null +++ b/.changeset/hip-onions-tan.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. diff --git a/.changeset/hip-pugs-teach.md b/.changeset/hip-pugs-teach.md new file mode 100644 index 0000000000..4a3820cecc --- /dev/null +++ b/.changeset/hip-pugs-teach.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/plugin-apollo-explorer': patch +'@backstage/plugin-cicd-statistics': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-org-react': patch +'@backstage/plugin-playlist': patch +--- + +Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages diff --git a/.changeset/hip-tables-prove.md b/.changeset/hip-tables-prove.md new file mode 100644 index 0000000000..bc2c4e83d6 --- /dev/null +++ b/.changeset/hip-tables-prove.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Updated the `mockServices.rootLogger` options to accept a single level option instead. diff --git a/.changeset/hot-wasps-cover.md b/.changeset/hot-wasps-cover.md new file mode 100644 index 0000000000..e142980b56 --- /dev/null +++ b/.changeset/hot-wasps-cover.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` diff --git a/.changeset/hungry-stingrays-type.md b/.changeset/hungry-stingrays-type.md new file mode 100644 index 0000000000..8cb11f67a5 --- /dev/null +++ b/.changeset/hungry-stingrays-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Keep the tech docs sync event stream alive even if it is taking a while to build. diff --git a/.changeset/itchy-chairs-punch.md b/.changeset/itchy-chairs-punch.md new file mode 100644 index 0000000000..034a9bbdae --- /dev/null +++ b/.changeset/itchy-chairs-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': patch +--- + +Aligned opaque type markers to all use a `$$type` property with namespacing. diff --git a/.changeset/little-jars-lay.md b/.changeset/little-jars-lay.md new file mode 100644 index 0000000000..f8851f7adc --- /dev/null +++ b/.changeset/little-jars-lay.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-user-settings-backend': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/backend-common': patch +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-events-backend': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-proxy-backend': patch +'@backstage/plugin-app-backend': patch +--- + +Updated usage of `createBackendPlugin`. diff --git a/.changeset/long-chefs-burn.md b/.changeset/long-chefs-burn.md new file mode 100644 index 0000000000..03a7b76db9 --- /dev/null +++ b/.changeset/long-chefs-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Updated database factory to pass service deps required for restoring database state during development. diff --git a/.changeset/many-pans-unite.md b/.changeset/many-pans-unite.md new file mode 100644 index 0000000000..59c068cec1 --- /dev/null +++ b/.changeset/many-pans-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-model': minor +--- + +Adds the tRPC API type to the catalog. diff --git a/.changeset/mean-squids-kneel.md b/.changeset/mean-squids-kneel.md new file mode 100644 index 0000000000..41a1bd4086 --- /dev/null +++ b/.changeset/mean-squids-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-vault': patch +--- + +Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. diff --git a/.changeset/nasty-beans-accept.md b/.changeset/nasty-beans-accept.md index 05ccb64c33..51b3e88e49 100644 --- a/.changeset/nasty-beans-accept.md +++ b/.changeset/nasty-beans-accept.md @@ -1,5 +1,5 @@ --- -'@backstage/create-app': minor +'@backstage/create-app': patch --- Update `SearchPage` template to use `SearchResult` extensions. diff --git a/.changeset/nasty-kids-deny.md b/.changeset/nasty-kids-deny.md new file mode 100644 index 0000000000..4a434eb1f6 --- /dev/null +++ b/.changeset/nasty-kids-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Use same table header color as @backstage/core-components Table to meet accessibility color contrast requirements. This change affects material-ui tables. diff --git a/.changeset/neat-schools-raise.md b/.changeset/neat-schools-raise.md new file mode 100644 index 0000000000..b778ba8795 --- /dev/null +++ b/.changeset/neat-schools-raise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Kubernetes proxy endpoint now accepts content types that are not json diff --git a/.changeset/nervous-phones-shout.md b/.changeset/nervous-phones-shout.md new file mode 100644 index 0000000000..a4e46b3be9 --- /dev/null +++ b/.changeset/nervous-phones-shout.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updates to match new `BackendFeature` type. diff --git a/.changeset/new-pumpkins-sleep.md b/.changeset/new-pumpkins-sleep.md new file mode 100644 index 0000000000..cc5b89806d --- /dev/null +++ b/.changeset/new-pumpkins-sleep.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-react': patch +--- + +bump `@rjsf` `v5` dependencies to 5.1.0 diff --git a/.changeset/nine-ravens-kiss.md b/.changeset/nine-ravens-kiss.md new file mode 100644 index 0000000000..a507db6b03 --- /dev/null +++ b/.changeset/nine-ravens-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': minor +--- + +The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. diff --git a/.changeset/odd-kangaroos-itch.md b/.changeset/odd-kangaroos-itch.md new file mode 100644 index 0000000000..8529e5fe04 --- /dev/null +++ b/.changeset/odd-kangaroos-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Fix #16245: The CatalogGraphCard has parameter naming errors for CatalogGraphPage diff --git a/.changeset/old-ways-know.md b/.changeset/old-ways-know.md new file mode 100644 index 0000000000..60a1a923e8 --- /dev/null +++ b/.changeset/old-ways-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. diff --git a/.changeset/perfect-pears-care.md b/.changeset/perfect-pears-care.md new file mode 100644 index 0000000000..2ea9f54a7f --- /dev/null +++ b/.changeset/perfect-pears-care.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-techdocs-backend': patch +'@backstage/plugin-techdocs-node': patch +'@techdocs/cli': patch +--- + +Added support for using a default `mkdocs.yml` configuration file when none is provided diff --git a/.changeset/poor-moons-confess.md b/.changeset/poor-moons-confess.md index 7fbdc292ed..7489a3c9f1 100644 --- a/.changeset/poor-moons-confess.md +++ b/.changeset/poor-moons-confess.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-catalog-backend-module-incremental-ingestion': minor +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch --- -Return EventSubscriber from addIncrementalEntityProvider to hook up to EventsBackend +Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` diff --git a/.changeset/pre.json b/.changeset/pre.json index 0d150702fb..01c51bcc4b 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.79", @@ -195,39 +195,149 @@ "@backstage/plugin-vault": "0.1.8", "@backstage/plugin-vault-backend": "0.2.6", "@backstage/plugin-xcmetrics": "0.2.34", - "@backstage/plugin-scaffolder-node": "0.0.0" + "@backstage/plugin-scaffolder-node": "0.0.0", + "@backstage/backend-dev-utils": "0.0.0", + "@backstage/eslint-plugin": "0.0.0", + "@backstage/plugin-entity-validation": "0.0.0", + "@backstage/plugin-graphql-voyager": "0.0.0", + "@backstage/plugin-lighthouse-backend": "0.0.0", + "@backstage/plugin-lighthouse-common": "0.0.0" }, "changesets": [ + "afraid-foxes-provide", + "afraid-planets-crash", + "brave-cougars-burn", + "breezy-ears-rule", "bright-eagles-love", + "bright-plums-cough", + "bright-teachers-compete", "brown-islands-own", "calm-avocados-exercise", + "chatty-owls-care", + "chilled-sheep-collect", + "clean-queens-judge", "cold-cycles-switch", + "cool-spoons-bathe", "create-app-1674561612", + "cuddly-boxes-agree", "cyan-deers-walk", + "dry-donkeys-cheer", + "dull-fishes-suffer", + "dull-gorillas-sing", "eight-falcons-explode", + "eight-hotels-sparkle", + "eight-vans-drum", + "eleven-shoes-crash", + "few-moons-accept", "flat-cups-itch", + "four-candles-add", + "four-rivers-enjoy", + "four-tables-fix", + "friendly-chefs-rule", "friendly-scissors-shop", + "gold-bulldogs-talk", "gold-lemons-eat", "gold-masks-sleep", + "great-goats-talk", + "green-adults-retire", + "green-guests-flow", + "grumpy-bottles-stare", + "grumpy-fireants-drop", + "happy-cows-moo", + "hip-chairs-double", + "hip-onions-tan", + "hip-pugs-teach", + "hip-tables-prove", + "hot-lions-cover", + "hot-wasps-cover", + "hungry-news-fix", + "itchy-chairs-punch", "itchy-goats-melt", "khaki-toes-care", + "late-rice-crash", "lazy-badgers-rule", "lazy-badgers-try", "lemon-tables-train", + "little-jars-lay", + "long-chefs-burn", "lovely-ladybugs-taste", + "many-nails-joke", + "many-pans-unite", + "mean-squids-kneel", + "modern-cats-worry", + "nasty-beans-accept", + "neat-schools-raise", + "neat-zebras-run", "nervous-apricots-whisper", "nervous-mangos-rhyme", + "nervous-phones-shout", + "new-pumpkins-sleep", + "nine-glasses-invent", + "nine-guests-compete", + "nine-ravens-kiss", + "ninety-hats-serve", + "old-knives-wonder", + "old-ways-know", "perfect-cheetahs-serve", "pink-falcons-serve", + "poor-moons-confess", + "popular-dancers-join", + "pretty-ladybugs-taste", + "proud-glasses-live", + "purple-feet-smile", "quick-ladybugs-reply", + "quick-mice-change", + "rare-berries-give", "rare-melons-battle", + "red-kiwis-compare", + "renovate-0b349f9", + "renovate-0c3644c", + "renovate-53e8b07", + "rich-snakes-rest", "rotten-mayflies-love", + "selfish-frogs-punch", + "serious-pigs-watch", + "sharp-lobsters-build", "shiny-years-tap", + "short-apes-relate", + "shy-buses-mix", + "shy-steaks-invite", + "silent-peas-fly", + "silly-buckets-joke", + "silly-socks-lie", "silly-turkeys-hang", + "silver-wolves-breathe", + "slow-carrots-sniff", + "slow-moles-sin", + "smart-dingos-raise", + "soft-actors-worry", + "soft-boxes-buy", + "soft-snails-notice", "spotty-coats-clean", "stale-dots-smile", + "stale-experts-punch", + "stupid-ladybugs-brake", "swift-fishes-smash", + "tall-falcons-teach", + "tall-tables-hide", + "tall-years-relate", + "tasty-jobs-help", + "thick-clocks-pump", + "thick-tables-travel", + "thin-donkeys-attack", + "thin-scissors-press", + "tough-jeans-camp", + "twenty-islands-wonder", "twenty-parents-relate", + "two-melons-lie", + "violet-tips-rhyme", + "weak-radios-sing", + "wicked-beers-walk", + "wild-donkeys-rescue", + "witty-moose-itch", + "yellow-roses-tell", + "young-beans-float", + "young-points-drop", "young-singers-learn" ] } diff --git a/.changeset/proud-glasses-live.md b/.changeset/proud-glasses-live.md new file mode 100644 index 0000000000..ded7a53ce7 --- /dev/null +++ b/.changeset/proud-glasses-live.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-adr': patch +--- + +Support displaying an icon on `AdrSearchResultListItem` diff --git a/.changeset/quick-mice-change.md b/.changeset/quick-mice-change.md new file mode 100644 index 0000000000..aeee24a021 --- /dev/null +++ b/.changeset/quick-mice-change.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-defaults': patch +--- + +Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` diff --git a/.changeset/quiet-pets-count.md b/.changeset/quiet-pets-count.md new file mode 100644 index 0000000000..bc7da8f3e7 --- /dev/null +++ b/.changeset/quiet-pets-count.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updated usage of `ServiceFactory`. diff --git a/.changeset/rare-berries-give.md b/.changeset/rare-berries-give.md new file mode 100644 index 0000000000..39e360bf48 --- /dev/null +++ b/.changeset/rare-berries-give.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Packages without a declared `backstage.role` are now ignored. diff --git a/.changeset/red-kiwis-compare.md b/.changeset/red-kiwis-compare.md new file mode 100644 index 0000000000..6045367105 --- /dev/null +++ b/.changeset/red-kiwis-compare.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. diff --git a/.changeset/red-toes-suffer.md b/.changeset/red-toes-suffer.md new file mode 100644 index 0000000000..3d819fb298 --- /dev/null +++ b/.changeset/red-toes-suffer.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-playlist-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-vault-backend': patch +--- + +Moving the backend-test-utils to devDependencies. diff --git a/.changeset/renovate-53e8b07.md b/.changeset/renovate-53e8b07.md new file mode 100644 index 0000000000..cb19d8fe8b --- /dev/null +++ b/.changeset/renovate-53e8b07.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. diff --git a/.changeset/rich-bags-sleep.md b/.changeset/rich-bags-sleep.md new file mode 100644 index 0000000000..14312ac7f4 --- /dev/null +++ b/.changeset/rich-bags-sleep.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +The PagerDutyCard now supports an optional `readOnly` property (``) for suppressing the rendering of the "Create Incident" button from the Backstage UI. diff --git a/.changeset/rotten-birds-build.md b/.changeset/rotten-birds-build.md new file mode 100644 index 0000000000..e165129998 --- /dev/null +++ b/.changeset/rotten-birds-build.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-microsoft-calendar': minor +--- + +Created a new plugin `@backstage/plugin-microsoft-calendar` to display events from a Microsoft Calendar. + +please refer to the [README.md](https://github.com/backstage/backstage/blob/master/plugins/microsoft-calendar/README.md) for step-by-step instructions to setup the plugin in your Backstage instance. diff --git a/.changeset/selfish-frogs-punch.md b/.changeset/selfish-frogs-punch.md new file mode 100644 index 0000000000..6484576af8 --- /dev/null +++ b/.changeset/selfish-frogs-punch.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: Switched out `LogMeta` type for `JsonObject`. diff --git a/.changeset/serious-grapes-brush.md b/.changeset/serious-grapes-brush.md new file mode 100644 index 0000000000..94eead7282 --- /dev/null +++ b/.changeset/serious-grapes-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Use github team slug and login annotations rather than entity name to infer location annotations diff --git a/.changeset/serious-pigs-watch.md b/.changeset/serious-pigs-watch.md new file mode 100644 index 0000000000..2efd8697f3 --- /dev/null +++ b/.changeset/serious-pigs-watch.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-search-react': patch +--- + +`ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + +Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. diff --git a/.changeset/short-apes-relate.md b/.changeset/short-apes-relate.md new file mode 100644 index 0000000000..d93c046a4d --- /dev/null +++ b/.changeset/short-apes-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. diff --git a/.changeset/shy-buses-mix.md b/.changeset/shy-buses-mix.md new file mode 100644 index 0000000000..b7db90d03c --- /dev/null +++ b/.changeset/shy-buses-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': minor +--- + +refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. diff --git a/.changeset/silent-peas-fly.md b/.changeset/silent-peas-fly.md new file mode 100644 index 0000000000..8148cb5d12 --- /dev/null +++ b/.changeset/silent-peas-fly.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong diff --git a/.changeset/silly-buckets-joke.md b/.changeset/silly-buckets-joke.md new file mode 100644 index 0000000000..113272c965 --- /dev/null +++ b/.changeset/silly-buckets-joke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration diff --git a/.changeset/silly-socks-lie.md b/.changeset/silly-socks-lie.md new file mode 100644 index 0000000000..ae7e1c0b2a --- /dev/null +++ b/.changeset/silly-socks-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-entity-validation': minor +--- + +First implementation for the entity validation UI. For more information refer to its `README.md`. diff --git a/.changeset/silver-badgers-heal.md b/.changeset/silver-badgers-heal.md new file mode 100644 index 0000000000..b1f239c3dc --- /dev/null +++ b/.changeset/silver-badgers-heal.md @@ -0,0 +1,35 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-techdocs': patch +--- + +Create a TechDocs `` addon that allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. + +Here's an example on how to use it in a Backstage app: + +```diff +import { + DefaultTechDocsHome, + TechDocsIndexPage, + TechDocsReaderPage, +} from '@backstage/plugin-techdocs'; +import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; ++import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + +const AppRoutes = () => { + + // other plugin routes + }> + + + } + > + ++ + + + ; +}; +``` diff --git a/.changeset/silver-wolves-breathe.md b/.changeset/silver-wolves-breathe.md new file mode 100644 index 0000000000..8c1529e142 --- /dev/null +++ b/.changeset/silver-wolves-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-sentry': minor +--- + +Add option to filter issues based on the time it was triggered diff --git a/.changeset/slow-carrots-sniff.md b/.changeset/slow-carrots-sniff.md new file mode 100644 index 0000000000..d32c2a281e --- /dev/null +++ b/.changeset/slow-carrots-sniff.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': minor +--- + +Improve performance when loading users via group membership. +Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + +Note, there are still additional per user calls made to load user avatars diff --git a/.changeset/slow-moles-sin.md b/.changeset/slow-moles-sin.md new file mode 100644 index 0000000000..02e1952312 --- /dev/null +++ b/.changeset/slow-moles-sin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-circleci': patch +--- + +Making workflow a link diff --git a/.changeset/slow-sloths-do.md b/.changeset/slow-sloths-do.md new file mode 100644 index 0000000000..2d86d477bf --- /dev/null +++ b/.changeset/slow-sloths-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Expose additional props on the `CatalogGraphCard` to allow for custom node & label rendering or kind/relation filtering. diff --git a/.changeset/soft-actors-worry.md b/.changeset/soft-actors-worry.md new file mode 100644 index 0000000000..5186499292 --- /dev/null +++ b/.changeset/soft-actors-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': minor +--- + +**BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` diff --git a/.changeset/soft-snails-notice.md b/.changeset/soft-snails-notice.md new file mode 100644 index 0000000000..ed39ee9591 --- /dev/null +++ b/.changeset/soft-snails-notice.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Prefer schema ordering of template properties during review content generation. diff --git a/.changeset/spotty-spiders-love.md b/.changeset/spotty-spiders-love.md new file mode 100644 index 0000000000..e0ac3b3cc7 --- /dev/null +++ b/.changeset/spotty-spiders-love.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Make catalog search result list a bit more customizable diff --git a/.changeset/stale-experts-punch.md b/.changeset/stale-experts-punch.md new file mode 100644 index 0000000000..85872bfffe --- /dev/null +++ b/.changeset/stale-experts-punch.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-user-settings-backend': patch +'@backstage/plugin-periskop-backend': patch +'@backstage/plugin-bazaar-backend': patch +'@backstage/plugin-kafka-backend': patch +'@backstage/plugin-proxy-backend': patch +--- + +Added a Backend System plugin feature diff --git a/.changeset/sweet-yaks-taste.md b/.changeset/sweet-yaks-taste.md new file mode 100644 index 0000000000..cbbbaea497 --- /dev/null +++ b/.changeset/sweet-yaks-taste.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cost-insights': patch +--- + +Fix bug in EntityCostsCard if cost aggregation array is empty. Allow title override on the Cost Insights Page diff --git a/.changeset/tall-falcons-teach.md b/.changeset/tall-falcons-teach.md new file mode 100644 index 0000000000..d6608a6597 --- /dev/null +++ b/.changeset/tall-falcons-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Navigation items in mobile sidebar now have aria label. diff --git a/.changeset/tall-tables-hide.md b/.changeset/tall-tables-hide.md new file mode 100644 index 0000000000..3e8011aff2 --- /dev/null +++ b/.changeset/tall-tables-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Updated README to include newer API options for incremental entity providers diff --git a/.changeset/tall-years-relate.md b/.changeset/tall-years-relate.md index 10198992ea..73a0e875b0 100644 --- a/.changeset/tall-years-relate.md +++ b/.changeset/tall-years-relate.md @@ -2,4 +2,4 @@ '@backstage/plugin-airbrake': patch --- -Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's catalog-info.yml has an airbrake id set in the metadata +Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's `catalog-info.yaml` has an airbrake id set in the metadata diff --git a/.changeset/tasty-jobs-help.md b/.changeset/tasty-jobs-help.md new file mode 100644 index 0000000000..ad1df8fb8c --- /dev/null +++ b/.changeset/tasty-jobs-help.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-graphql-voyager': minor +--- + +Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + +For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. diff --git a/.changeset/thick-tables-travel.md b/.changeset/thick-tables-travel.md new file mode 100644 index 0000000000..d74ed18b8a --- /dev/null +++ b/.changeset/thick-tables-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-events-node': patch +--- + +Make `EventParams` typed for implementing tidier event handling. diff --git a/.changeset/thin-donkeys-attack.md b/.changeset/thin-donkeys-attack.md new file mode 100644 index 0000000000..2fd0aebb6a --- /dev/null +++ b/.changeset/thin-donkeys-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-test-utils': patch +--- + +Removed the `ref` from all `mockServices`. diff --git a/.changeset/thin-scissors-press.md b/.changeset/thin-scissors-press.md new file mode 100644 index 0000000000..2891d4ca66 --- /dev/null +++ b/.changeset/thin-scissors-press.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-azure-sites': patch +--- + +Fixed `AzureSites` plugin start and stop issue #15904 +Fixed `AzureSites` UI load issue #15907 diff --git a/.changeset/three-geckos-press.md b/.changeset/three-geckos-press.md new file mode 100644 index 0000000000..fc1af4fdc0 --- /dev/null +++ b/.changeset/three-geckos-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Implement a `showCounts` option to display result counts per type in `SearchType.Accordion` diff --git a/.changeset/tidy-kings-cough.md b/.changeset/tidy-kings-cough.md new file mode 100644 index 0000000000..e908572c8b --- /dev/null +++ b/.changeset/tidy-kings-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +The name of the header used to specify a cluster to the proxy endpoint is now visible in the API reference. diff --git a/.changeset/tough-jeans-camp.md b/.changeset/tough-jeans-camp.md new file mode 100644 index 0000000000..8c7a53190f --- /dev/null +++ b/.changeset/tough-jeans-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/eslint-plugin': minor +--- + +Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. diff --git a/.changeset/twenty-islands-wonder.md b/.changeset/twenty-islands-wonder.md new file mode 100644 index 0000000000..fe3c5a05c8 --- /dev/null +++ b/.changeset/twenty-islands-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +Aligned buttons on "Unregister entity" dialog to keep them on the same line diff --git a/.changeset/twenty-pugs-explain.md b/.changeset/twenty-pugs-explain.md new file mode 100644 index 0000000000..9ac77d2ffb --- /dev/null +++ b/.changeset/twenty-pugs-explain.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +**BREAKING**: The `CacheService` has been changed to remove the indirection of `getClient`, instead making the `CacheClient` methods directly available on the `CacheService`. In order to allow for the creation of clients with default options, there is now a new `.withOptions` method that must be implemented as part of the service interface. diff --git a/.changeset/violet-tips-rhyme.md b/.changeset/violet-tips-rhyme.md new file mode 100644 index 0000000000..c2d95cfbf9 --- /dev/null +++ b/.changeset/violet-tips-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. diff --git a/.changeset/weak-radios-sing.md b/.changeset/weak-radios-sing.md new file mode 100644 index 0000000000..dff287b565 --- /dev/null +++ b/.changeset/weak-radios-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. diff --git a/.changeset/wicked-beers-walk.md b/.changeset/wicked-beers-walk.md new file mode 100644 index 0000000000..160a171eb1 --- /dev/null +++ b/.changeset/wicked-beers-walk.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. diff --git a/.changeset/wild-donkeys-rescue.md b/.changeset/wild-donkeys-rescue.md new file mode 100644 index 0000000000..43dc3743bb --- /dev/null +++ b/.changeset/wild-donkeys-rescue.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-test-utils': patch +'@backstage/backend-app-api': patch +--- + +Updated usages of `LogMeta`. diff --git a/.changeset/wild-melons-shout.md b/.changeset/wild-melons-shout.md new file mode 100644 index 0000000000..5a79612f22 --- /dev/null +++ b/.changeset/wild-melons-shout.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +Switch `ServiceFactory` to be an opaque type, keeping only the `service` field as public API, but also adding a type parameter for the service scope. diff --git a/.changeset/yellow-roses-tell.md b/.changeset/yellow-roses-tell.md new file mode 100644 index 0000000000..ad645df294 --- /dev/null +++ b/.changeset/yellow-roses-tell.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-plugin-api': minor +--- + +Switched `BackendFeature` to be an opaque type. diff --git a/.changeset/young-beans-float.md b/.changeset/young-beans-float.md new file mode 100644 index 0000000000..ef52b2080a --- /dev/null +++ b/.changeset/young-beans-float.md @@ -0,0 +1,24 @@ +--- +'@backstage/plugin-lighthouse': minor +--- + +Require @backstage/plugin-lighthouse-common package where API implementation moved to. + +**BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + +- `Audit` +- `AuditBase` +- `AuditCompleted` +- `AuditFailed` +- `AuditRunning` +- `FetchError` +- `LASListRequest` +- `LASListResponse` +- `LighthouseApi` +- `LighthouseCategoryAbbr` +- `LighthouseCategoryId` +- `LighthouseConfigSettings` +- `LighthouseRestApi` +- `TriggerAuditPayload` +- `Website` +- `WebsiteListResponse` diff --git a/.changeset/young-points-drop.md b/.changeset/young-points-drop.md new file mode 100644 index 0000000000..4309d54c2c --- /dev/null +++ b/.changeset/young-points-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 82d868a408..1c6171cb01 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,78 +4,78 @@ # The last matching pattern takes precedence. # https://help.github.com/articles/about-codeowners/ -* @backstage/reviewers -yarn.lock @backstage/reviewers @backstage-service -*/yarn.lock @backstage/reviewers @backstage-service -/.changeset/cost-insights-* @backstage/reviewers @backstage/silver-lining -/.changeset @backstage/reviewers @backstage/techdocs-core -/cypress/src/integration/plugins/techdocs.spec.ts @backstage/reviewers @backstage/techdocs-core -/docs/assets/search @backstage/reviewers @backstage/techdocs-core -/docs/features/search @backstage/reviewers @backstage/techdocs-core -/docs/features/techdocs @backstage/reviewers @backstage/techdocs-core -/docs/plugins/integrating-search-into-plugins.md @backstage/reviewers @backstage/techdocs-core -/packages/techdocs-cli @backstage/reviewers @backstage/techdocs-core -/packages/techdocs-cli-embedded-app @backstage/reviewers @backstage/techdocs-core -/plugins/adr @backstage/reviewers @kuangp -/plugins/adr-* @backstage/reviewers @kuangp -/plugins/allure @backstage/reviewers @deepak-bhardwaj-ps -/plugins/apache-airflow @backstage/reviewers @cmpadden -/plugins/api-docs @backstage/reviewers @backstage/sda-se-reviewers -/plugins/azure-devops @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-backend @backstage/reviewers @marleypowell @awanlin -/plugins/azure-devops-common @backstage/reviewers @marleypowell @awanlin -/plugins/bitbucket-cloud-common @backstage/reviewers @pjungermann -/plugins/bitrise @backstage/reviewers @backstage/sda-se-reviewers -/plugins/catalog @backstage/reviewers @backstage/catalog-core -/plugins/catalog-* @backstage/reviewers @backstage/catalog-core -/plugins/catalog-backend-module-aws @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-backend-module-bitbucket-cloud @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-backend-module-msgraph @backstage/reviewers @backstage/catalog-core @pjungermann -/plugins/catalog-graph @backstage/reviewers @backstage/catalog-core @backstage/sda-se-reviewers -/plugins/circleci @backstage/reviewers @adamdmharvey -/plugins/cloudbuild @backstage/reviewers @trivago/ebarrios -/plugins/code-coverage @backstage/reviewers @alde @nissayeva -/plugins/code-coverage-backend @backstage/reviewers @alde @nissayeva -/plugins/cost-insights @backstage/reviewers @backstage/silver-lining -/plugins/cost-insights-* @backstage/reviewers @backstage/silver-lining -/plugins/events-backend @backstage/reviewers @pjungermann -/plugins/events-backend-module-aws-sqs @backstage/reviewers @pjungermann -/plugins/events-backend-module-azure @backstage/reviewers @pjungermann -/plugins/events-backend-module-bitbucket-cloud @backstage/reviewers @pjungermann -/plugins/events-backend-module-gerrit @backstage/reviewers @pjungermann -/plugins/events-backend-module-github @backstage/reviewers @pjungermann -/plugins/events-backend-module-gitlab @backstage/reviewers @pjungermann -/plugins/events-backend-test-utils @backstage/reviewers @pjungermann -/plugins/events-node @backstage/reviewers @pjungermann -/plugins/explore @backstage/reviewers @backstage/sda-se-reviewers -/plugins/explore-react @backstage/reviewers @backstage/sda-se-reviewers -/plugins/fossa @backstage/reviewers @backstage/sda-se-reviewers -/plugins/gcalendar @backstage/reviewers @szubster @ptychu @kielosz @alexrybch -/plugins/git-release-manager @backstage/reviewers @erikengervall -/plugins/home @backstage/reviewers @backstage/techdocs-core -/plugins/ilert @backstage/reviewers @yacut -/plugins/jenkins @backstage/reviewers @timja -/plugins/jenkins-backend @backstage/reviewers @timja -/plugins/kafka @backstage/reviewers @nirga @andrewthauer -/plugins/kafka-backend @backstage/reviewers @nirga @andrewthauer -/plugins/kubernetes @backstage/reviewers @backstage/warpspeed -/plugins/kubernetes-* @backstage/reviewers @backstage/warpspeed -/plugins/newrelic-dashboard @backstage/reviewers @mufaddal7 -/plugins/playlist @backstage/reviewers @kuangp -/plugins/playlist-* @backstage/reviewers @kuangp -/plugins/rollbar @backstage/reviewers @andrewthauer -/plugins/rollbar-backend @backstage/reviewers @andrewthauer -/plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski -/plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka -/plugins/search @backstage/reviewers @backstage/techdocs-core -/plugins/search-* @backstage/reviewers @backstage/techdocs-core -/plugins/sonarqube @backstage/reviewers @backstage/sda-se-reviewers -/plugins/stack-overflow @backstage/reviewers @backstage/techdocs-core -/plugins/stack-overflow-backend @backstage/reviewers @backstage/techdocs-core -/plugins/techdocs @backstage/reviewers @backstage/techdocs-core -/plugins/techdocs-* @backstage/reviewers @backstage/techdocs-core -/plugins/user-settings-backend @backstage/reviewers @backstage/sda-se-reviewers -/tech-insights-backend @backstage/reviewers @xantier @iain-b -/tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b -/tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b -/tech-insights-tech-insights-node @backstage/reviewers @xantier @iain-b +* @backstage/maintainers +yarn.lock @backstage/maintainers @backstage-service +*/yarn.lock @backstage/maintainers @backstage-service +/.changeset/*.md +/cypress/src/integration/plugins/techdocs.spec.ts @backstage/techdocs-core +/docs/assets/search @backstage/techdocs-core +/docs/features/search @backstage/techdocs-core +/docs/features/techdocs @backstage/techdocs-core +/docs/plugins/integrating-search-into-plugins.md @backstage/techdocs-core +/packages/techdocs-cli @backstage/techdocs-core +/packages/techdocs-cli-embedded-app @backstage/techdocs-core +/plugins/adr @backstage/maintainers @kuangp +/plugins/adr-* @backstage/maintainers @kuangp +/plugins/allure @backstage/maintainers @deepak-bhardwaj-ps +/plugins/apache-airflow @backstage/maintainers @cmpadden +/plugins/api-docs @backstage/maintainers @backstage/sda-se-reviewers +/plugins/azure-devops @backstage/maintainers @marleypowell @awanlin +/plugins/azure-devops-backend @backstage/maintainers @marleypowell @awanlin +/plugins/azure-devops-common @backstage/maintainers @marleypowell @awanlin +/plugins/bitbucket-cloud-common @backstage/maintainers @pjungermann +/plugins/bitrise @backstage/maintainers @backstage/sda-se-reviewers +/plugins/catalog @backstage/maintainers @backstage/catalog-core +/plugins/catalog-* @backstage/maintainers @backstage/catalog-core +/plugins/catalog-backend-module-aws @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-backend-module-bitbucket-cloud @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/catalog-core @pjungermann +/plugins/catalog-graph @backstage/maintainers @backstage/catalog-core @backstage/sda-se-reviewers +/plugins/circleci @backstage/maintainers @adamdmharvey +/plugins/cloudbuild @backstage/maintainers @trivago/ebarrios +/plugins/code-coverage @backstage/maintainers @alde @nissayeva +/plugins/code-coverage-backend @backstage/maintainers @alde @nissayeva +/plugins/cost-insights @backstage/maintainers @backstage/silver-lining +/plugins/cost-insights-* @backstage/maintainers @backstage/silver-lining +/plugins/events-backend @backstage/maintainers @pjungermann +/plugins/events-backend-module-aws-sqs @backstage/maintainers @pjungermann +/plugins/events-backend-module-azure @backstage/maintainers @pjungermann +/plugins/events-backend-module-bitbucket-cloud @backstage/maintainers @pjungermann +/plugins/events-backend-module-gerrit @backstage/maintainers @pjungermann +/plugins/events-backend-module-github @backstage/maintainers @pjungermann +/plugins/events-backend-module-gitlab @backstage/maintainers @pjungermann +/plugins/events-backend-test-utils @backstage/maintainers @pjungermann +/plugins/events-node @backstage/maintainers @pjungermann +/plugins/explore @backstage/maintainers @backstage/sda-se-reviewers +/plugins/explore-react @backstage/maintainers @backstage/sda-se-reviewers +/plugins/fossa @backstage/maintainers @backstage/sda-se-reviewers +/plugins/gcalendar @backstage/maintainers @szubster @ptychu @kielosz @alexrybch +/plugins/git-release-manager @backstage/maintainers @erikengervall +/plugins/home @backstage/techdocs-core +/plugins/ilert @backstage/maintainers @yacut +/plugins/jenkins @backstage/maintainers @timja +/plugins/jenkins-backend @backstage/maintainers @timja +/plugins/kafka @backstage/maintainers @nirga @andrewthauer +/plugins/kafka-backend @backstage/maintainers @nirga @andrewthauer +/plugins/kubernetes @backstage/maintainers @backstage/warpspeed +/plugins/kubernetes-* @backstage/maintainers @backstage/warpspeed +/plugins/microsoft-calendar @backstage/maintainers @abhay-soni-developer +/plugins/newrelic-dashboard @backstage/maintainers @mufaddal7 +/plugins/playlist @backstage/maintainers @kuangp +/plugins/playlist-* @backstage/maintainers @kuangp +/plugins/rollbar @backstage/maintainers @andrewthauer +/plugins/rollbar-backend @backstage/maintainers @andrewthauer +/plugins/scaffolder-backend-module-rails @backstage/maintainers @angeliski +/plugins/scaffolder-backend-module-yeoman @backstage/maintainers @pawelmitka +/plugins/search @backstage/techdocs-core +/plugins/search-* @backstage/techdocs-core +/plugins/sonarqube @backstage/maintainers @backstage/sda-se-reviewers +/plugins/stack-overflow @backstage/techdocs-core +/plugins/stack-overflow-backend @backstage/techdocs-core +/plugins/techdocs @backstage/techdocs-core +/plugins/techdocs-* @backstage/techdocs-core +/plugins/user-settings-backend @backstage/maintainers @backstage/sda-se-reviewers +/tech-insights-backend @backstage/maintainers @xantier @iain-b +/tech-insights-backend-module-jsonfc @backstage/maintainers @xantier @iain-b +/tech-insights-tech-insights-common @backstage/maintainers @xantier @iain-b +/tech-insights-tech-insights-node @backstage/maintainers @xantier @iain-b diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index d8c962ecc2..e6380a17f0 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -9,6 +9,7 @@ Airbrake Airbrakes Alaria Alef +allowlisted Anddddd Apdex api @@ -23,6 +24,7 @@ Avro backend's backported backporting +BEPs Bigtable Billett bitbucket @@ -95,6 +97,7 @@ dockerfiles Dockerize dockerode Docusaurus +Dominik DOMPurify don'ts dynatrace @@ -119,6 +122,7 @@ Firekube Firestore Fiverr Francesco +Frontside gerrit Gerrit gitbeaker @@ -138,6 +142,7 @@ Hackathons haproxy hardcoded Helidon +Henneke Heroku hoc horizontalpodautoscalers @@ -167,12 +172,14 @@ jsonnet jsx JWTs Kaewkasi +Kaswell Keyv Knex KPIs +Kuang kubectl kubernetes -kubernetes +Lainfiesta ldap learnings Leasot @@ -336,6 +343,7 @@ subfolders subheader subheaders subkey +subpath subroutes subtree superfences @@ -412,8 +420,3 @@ zod Zolotusky zoomable zsh -Lainfiesta -allowlisted -Dominik -Henneke -Kuang diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index e18aa9d428..aaf0bb1294 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -28,13 +28,13 @@ jobs: ref: 'refs/pull/${{ github.event.pull_request.number }}/merge' - name: fetch base run: git fetch --depth 1 origin ${{ github.base_ref }} - - uses: backstage/actions/changeset-feedback@v0.5.13 + - uses: backstage/actions/changeset-feedback@v0.6.0 name: Generate feedback with: - diffRef: 'origin/master' + diff-ref: 'origin/master' marker: issue-number: ${{ github.event.pull_request.number }} - botUsername: backstage-goalie[bot] + bot-username: backstage-goalie[bot] app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10db591f4c..16573cf5b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -63,7 +63,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -181,7 +181,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index dc221c1a1e..2e6573ede8 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,7 +8,7 @@ jobs: cron: runs-on: ubuntu-latest steps: - - uses: backstage/actions/cron@v0.5.13 + - uses: backstage/actions/cron@v0.6.0 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index d8470d4124..909a36199c 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -26,7 +26,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 5f337ace3e..c9cd22640c 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -26,7 +26,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index c05b850883..fa43271a96 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -68,7 +68,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} @@ -145,7 +145,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index d16d0b55d7..9f2e5827be 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,4 +10,4 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Issue sync - uses: backstage/actions/issue-sync@v0.5.13 + uses: backstage/actions/issue-sync@v0.6.0 diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 11b590809a..261ce56177 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -35,7 +35,7 @@ jobs: const prNumber = artifact.name.slice('pr_number-'.length) core.setOutput('pr-number', prNumber); - - uses: backstage/actions/re-review@v0.5.13 + - uses: backstage/actions/re-review@v0.6.0 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index acbd11aece..db7d141abd 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,12 +18,12 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: PR sync - uses: backstage/actions/pr-sync@v0.5.13 + uses: backstage/actions/pr-sync@v0.6.2 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }} installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }} project-id: PVT_kwDOBFKqdc02LQ - excluded-users: ${{ secrets.OOO_USERS }} + auto-assign: false owning-teams: '@backstage/techdocs-core' diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 19cc5f8045..b84fe5c2e6 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -20,7 +20,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index c6d00ecd28..8cf6991aaf 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -53,10 +53,6 @@ jobs: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while script: | - const releaseVersion = require('./backstage/package.json').version; - if(releaseVersion.includes('next')) { - return; - } console.log('Dispatching upgrade helper sync'); await github.rest.actions.createWorkflowDispatch({ owner: 'backstage', @@ -65,6 +61,6 @@ jobs: ref: 'master', inputs: { version: require('./backstage/packages/create-app/package.json').version, - releaseVersion + releaseVersion: require('./backstage/package.json').version }, }); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 9dcc9f63ef..dfd114c66a 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -23,7 +23,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 5c8e179958..714b108898 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -27,7 +27,7 @@ jobs: registry-url: https://registry.npmjs.org/ - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: linux-v16 diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index f687e4f5a4..16ddb04086 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -52,7 +52,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_kubernetes.yml b/.github/workflows/verify_kubernetes.yml index 7fbcf9fa3f..6d8a7682b5 100644 --- a/.github/workflows/verify_kubernetes.yml +++ b/.github/workflows/verify_kubernetes.yml @@ -28,7 +28,7 @@ jobs: registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 0e63393af8..38b685c539 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -35,7 +35,7 @@ jobs: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.5.13 + uses: backstage/actions/yarn-install@v0.6.0 with: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: storybook yarn install diff --git a/ADOPTERS.md b/ADOPTERS.md index 965cf06727..4329a00664 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -186,7 +186,7 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Cho Tot](https://www.chotot.com) | [Chotot Team](mailto:sre@chotot.vn) | Internal developer portal, service catalog with CI/CD tools. | | [William Hill](https://www.williamhillgroup.com/) | [Pat Mills](mailto:pat.mills@williamhill.com), [Nathan Flynn](mailto:nflynn@williamhill.co.uk), and [Nishkarsh Raj](mailto:nishkarsh.raj@williamhill.co.uk) | William Hill are leveraging Backstage to build our Engineering Portal. Our mission is to centralize the software catalog inventory to enable service discoverability, reduce the onboarding time for new Engineers, provide a single pane of glass to accelerate Developer Productivity and Save Engineers time. Our aspiration is to create an InnerSource community focussed on organization-wide patterns that are re-usable and can be self-served with the Scaffolder. | | [Vodafone NewZealand Limited](https://vodafone.co.nz) | [Ankit Gupta](mailto:ankit.gupta@vodafone.nz), [DevOps COE](mailto:devopstooling@vodafone.nz) | Vodafone NZ are leveraging Backstage to build centralised and self service Engineering Portal. Our mission is to standardised Pipeline templates across the Engineering teams, One shop stop to create the pipelines and repository with a template approach which reduces creation part from days to minutes and no wait time for developers. A unified view for Azure DevOps pipeline, Azure Repo pull requests, Deployment status from Azure RedHat Openshift-ArgoCD and SonarQube Security and code quality scans report on a single pan to provide a streamlined view for all microservices across the app stack. | -| [Coamo](http://www.coamo.com.br) | [@holiiveira](https://github.com/holiiveira), [@gpxlnx](https://github.com/gpxlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place. | +| [Coamo](http://www.coamo.com.br) | [Henrique Oliveira](https://www.linkedin.com/in/oliveirah/), [Guilherme Xavier](https://br.linkedin.com/in/guilhermexavierlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place. | | [Exclaimer](https://www.exclaimer.com/) | [Marley Powell](mailto:marley.powell@exclaimer.com) | Developer portal, service catalog and documentation | | [Edge Consulting](https://egde.no/) | [Øyvind Brekkhus Sandåker](mailto:oyvindbs@egde.no) | Using it as a Software Catalog to get an overview of our systems, for ourselves and our customers. | | [CRV](https://crv4all.com) | [Pepijn Schildkamp](mailto:pepijn.schildkamp@crv4all.com) | diff --git a/STYLE.md b/STYLE.md index 87e0644759..e38354ae1d 100644 --- a/STYLE.md +++ b/STYLE.md @@ -94,6 +94,13 @@ This section describes guidelines for designing public APIs. It can also be appl /* ... */ } + // In order to make a private constructor available for testing you can use a + // static factory marked as `@internal`, which will not show up in the public API. + /** @internal */ + static forTesting(internalOptions?: { ... }) { + return new DefaultImageLoader(internalOptions); + } + private constructor(/* ... */) { /* ... */ } diff --git a/cypress/.eslintrc.js b/cypress/.eslintrc.js index a77de4a629..07f264452d 100644 --- a/cypress/.eslintrc.js +++ b/cypress/.eslintrc.js @@ -2,15 +2,6 @@ module.exports = { extends: [require.resolve('@backstage/cli/config/eslint.backend')], rules: { 'no-console': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - }, - ], 'jest/valid-expect': 'off', 'jest/expect-expect': 'off', 'no-restricted-syntax': 'off', diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts new file mode 100644 index 0000000000..fd4db77d61 --- /dev/null +++ b/cypress/support/commands.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. + */ + +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts new file mode 100644 index 0000000000..c71790471e --- /dev/null +++ b/cypress/support/e2e.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// This example support/e2e.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands'; + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/cypress/yarn.lock b/cypress/yarn.lock index ded043cdaf..36dd0b056d 100644 --- a/cypress/yarn.lock +++ b/cypress/yarn.lock @@ -1415,22 +1415,22 @@ __metadata: linkType: hard "typescript@npm:^4.1.3": - version: 4.9.4 - resolution: "typescript@npm:4.9.4" + version: 4.9.5 + resolution: "typescript@npm:4.9.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9 + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db languageName: node linkType: hard "typescript@patch:typescript@^4.1.3#~builtin": - version: 4.9.4 - resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin::version=4.9.4&hash=a1c5e5" + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=a1c5e5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 37f6e2c3c5e2aa5934b85b0fddbf32eeac8b1bacf3a5b51d01946936d03f5377fe86255d4e5a4ae628fd0cd553386355ad362c57f13b4635064400f3e8e05b9d + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard diff --git a/docs/assets/auth/gcp-iap-jwt-audience-code-popup.png b/docs/assets/auth/gcp-iap-jwt-audience-code-popup.png new file mode 100644 index 0000000000..72b69b3b01 Binary files /dev/null and b/docs/assets/auth/gcp-iap-jwt-audience-code-popup.png differ diff --git a/docs/assets/permissions/permission-framework-overview.drawio.svg b/docs/assets/permissions/permission-framework-overview.drawio.svg index c7e628f8a6..3740384748 100644 --- a/docs/assets/permissions/permission-framework-overview.drawio.svg +++ b/docs/assets/permissions/permission-framework-overview.drawio.svg @@ -1,4 +1,4 @@ -
    User
    User
    Plugin
    Plugin
    Permission Response
    Permission Response
    Permission Framework
    Permission Framework
    Action
    (Read request)
    Action...
    Resources
    Resources
    Resource read permission
    Resource read...
    Permission Policy
    Permission Policy
    Permission Request
    Permission Request
    Provided by Backstage
    Provided by Backstage
    Configured by integrators
    Configured by integrators
    Configured by plugin authors
    Configured by plugin authors
    Permission Backend
    Permission hooks
    Integration helpers
    ...
    Permission Backend...
    1
    1
    2
    2
    3
    3
    4
    4
    Text is not SVG - cannot display
    \ No newline at end of file +
    User
    User
    Plugin
    Plugin
    Permission Response
    Permission Response
    Permission Framework
    Permission Framework
    Action
    (Read request)
    Action...
    Resources
    Resources
    Resource read permission
    Resource read...
    Permission Policy
    Permission Policy
    Permission Request
    Permission Request
    Provided by Backstage
    Provided by Backstage
    Configured by integrators
    Configured by integrators
    Configured by plugin authors
    Configured by plugin authors
    Permission Backend
    Permission hooks
    Integration helpers
    ...
    Permission Backend...
    1
    1
    2
    2
    3
    3
    4
    4
    5
    5
    User gets a response
    User gets a response
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/assets/software-catalog/software-model-entities.drawio.svg b/docs/assets/software-catalog/software-model-entities.drawio.svg old mode 100755 new mode 100644 index e14cc93e62..d087583245 --- a/docs/assets/software-catalog/software-model-entities.drawio.svg +++ b/docs/assets/software-catalog/software-model-entities.drawio.svg @@ -1,4 +1,4 @@ -
    Domain
    Domain
    partOf
    partOf
    System
    System
    dependsOn
    dependsOn
    partOf
    partOf
    Resource
    (e.g. SQL Database, S3 bucket, ...)
    Resource...
    consumesAPI
    consumesAPI
    API
    (e.g. OpenAPI, gRPC API, Avro, Dataset, ...)
    API...
    providesAPI
    providesAPI
    partOf
    partOf
    Component
    (e.g. backend service, data pipeline ...)
    Component...
    partOf
    partOf
    dependsOn
    dependsOn
    Text is not SVG - cannot display
    \ No newline at end of file +
    Domain
    (e.g.  domain
    models, metrics, KPIs, business purpose)
    Domain...
    partOf
    partOf
    System
    Collection of entities that cooperate to perform some function
    System...
    dependsOn
    dependsOn
    partOf
    partOf
    Resource
    (e.g. SQL Database, S3 bucket, ...)
    Resource...
    consumesAPI
    consumesAPI
    API
    (e.g. OpenAPI, gRPC API, Avro, Dataset, ...)
    API...
    providesAPI
    providesAPI
    partOf
    partOf
    Component
    (e.g. backend service, data pipeline ...)
    Component...
    partOf
    partOf
    dependsOn
    dependsOn
    Kind: Group
    Kind: Group
    Kind: User
    Kind: User
    OwnerOf
    OwnerOf
    OwnedBy
    OwnedBy
    Service
    Service
    website
    website
    website
    website
    Types
    Types
    service
    service
    website
    website
    library
    library
    asyncapi
    asyncapi
    graphql
    graphql
    grpc
    grpc
    Types
    Types
    openapi
    openapi
    business-unit
    business-unit
    product-area
    product-area
    root
    root
    Types
    Types
    team
    team
    s3-bucket
    s3-bucket
    cluster
    cluster
    Types
    Types
    database
    database
    Kind: Template
    Parameters rendered in the
    frontend and the steps executed in  the scaffolding process
    Kind: Template...
    Kind: Location
    a marker that references other places to look for catalog data
    Kind: Location...
    memberOf
    memberOf
    hasMember
    hasMember
    parentOf
    parentOf
    childOf
    childOf
    Text is not SVG - cannot display
    \ No newline at end of file diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md index f9a78bbc71..36eece85c5 100644 --- a/docs/auth/google/gcp-iap-auth.md +++ b/docs/auth/google/gcp-iap-auth.md @@ -29,7 +29,9 @@ auth: jwtHeader: x-custom-header # Optional: Only if you are using a custom header for the IAP JWT ``` -You can find the project number and service ID in the Google Cloud Console. +The full `audience` value can be obtained by visiting your [Identity-Aware Proxy Google Cloud console](https://console.cloud.google.com/security/iap), selecting your project, finding your Backend Service to proxy, clicking the 3 vertical dots then "Get JWT Audience Code", and copying from the resulting popup, which will look similar to the following: + +![Identity-Aware Proxy JWT Audience Code popup](../../assets/auth/gcp-iap-jwt-audience-code-popup.png) This config section must be in place for the provider to load at all. Now let's add the provider itself. diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index 88ba3262df..a9f08c7907 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -6,6 +6,8 @@ sidebar_label: System Architecture description: The structure and architecture of the new Backend System and its component parts --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## Building Blocks This section introduces the high-level building blocks upon which this new diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 69b74e7dd3..53670aba12 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -6,6 +6,8 @@ sidebar_label: Backend description: Backend instances --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## The Backend Instance This is the main entry point for creating a backend. It does not have any functionality in and of itself, but is simply responsible for wiring things together. diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index 96b82d7e95..875cb3aaea 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -6,6 +6,8 @@ sidebar_label: Services description: Services for backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Backend services provide shared functionality available to all backend plugins and modules. They are made available through service references that embed a type that represents the service interface, similar to how [Utility APIs](../../api/utility-apis.md) work in the Backstage frontend system. To use a service in your plugin or module you request an implementation of that service using the service reference. The system surrounding services exists to provide a level of indirection between the service interfaces and their implementation. It is an implementation of dependency injection, where each backend instance is the dependency injection container. The implementation for each service is provided by a service factory, which encapsulates the logic for how each service instance is created. @@ -59,7 +61,7 @@ class DefaultFooService implements FooService { } } -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: { bar: barServiceRef }, factory({ bar }) { @@ -73,7 +75,7 @@ To create a service factory we need to provide a reference to the `service` for If you need the creation of the service instance to be asynchronous, you can make the `factory` function async. For example: ```ts -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: {}, async factory() { @@ -92,18 +94,18 @@ To install a service factory in a backend instance, we pass it in through the `s ```ts const backend = createBackend({ - services: [fooFactory()], + services: [fooServiceFactory()], }); ``` -Note that we call `fooFactory` to create the service factory instance. This is because `createServiceFactory` always returns a factory function that creates the actual service factory. This is done to always allow for options to be added to the service factory in the future, without breaking existing code. To add options to your service factory, you wrap the object passed to `createServiceFactory` in a callback that accepts the desired options. For example: +Note that we call `fooServiceFactory` to create the service factory instance. This is because `createServiceFactory` always returns a factory function that creates the actual service factory. This is done to always allow for options to be added to the service factory in the future, without breaking existing code. To add options to your service factory, you wrap the object passed to `createServiceFactory` in a callback that accepts the desired options. For example: ```ts export interface FooFactoryOptions { mode: 'eager' | 'lazy'; } -export const fooFactory = createServiceFactory( +export const fooServiceFactory = createServiceFactory( (options?: FooFactoryOptions) => ({ service: fooServiceRef, deps: { bar: barServiceRef }, @@ -118,7 +120,7 @@ This lets us use the options to customize the factory implementation in any way ```ts const backend = createBackend({ - services: [fooFactory({ mode: 'eager' })], + services: [fooServiceFactory({ mode: 'eager' })], }); ``` @@ -162,7 +164,7 @@ Plugin scoped services have access to a plugin metadata service, which is a spec The plugin metadata service is the base for all plugin specific customizations for services. For example, the default implementation of the plugin scoped logger service uses the plugin metadata service to attach the plugin ID as a field in all log messages: ```ts -export const loggerFactory = createServiceFactory({ +export const loggerServiceFactory = createServiceFactory({ service: coreServices.logger, deps: { rootLogger: coreServices.rootLogger, @@ -181,7 +183,7 @@ Some services may benefit from having a context that is shared across all instan The root context is defined as part of the service factory by passing the `createRootContext` option: ```ts -export const fooFactory = createServiceFactory({ +export const fooServiceFactory = createServiceFactory({ service: fooServiceRef, deps: { rootLogger: coreServices.rootLogger, bar: barServiceRef }, createRootContext({ rootLogger }) { diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index f535268b2a..e73f086c43 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -6,6 +6,8 @@ sidebar_label: Plugins description: Backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Plugins provide the actual base features of a Backstage backend. Each plugin operates completely independently of all other plugins and they only communicate with each other through network calls. This means that there is a strong degree of isolation between plugins, and that each plugin can be considered a separate microservice. While a default Backstage project has all plugins installed within a single backend, it is also possible to split this setup into multiple backends, with each backend housing one or more plugins. ## Defining a Plugin @@ -20,7 +22,7 @@ import { } from '@backstage/backend-plugin-api'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -51,7 +53,7 @@ export interface ExamplePluginOptions { export const examplePlugin = createBackendPlugin( (options?: ExamplePluginOptions) => ({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index f82fde3561..278c565472 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -6,6 +6,8 @@ sidebar_label: Extension Points description: Extension points of backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + While plugins are able to accept options for lightweight forms of customization and extension, you quickly hit a limit where you need something more powerful to allow users to extend your plugin. For this purpose, the backend system provides a mechanism for plugins to provide extension points, which can be used to expose deeper customizations for your plugin. Extension points are used by modules, which are installed in the backend adjacent to plugins. Modules are covered more in-depth in the [next section](./06-modules.md). Extension points are quite similar to services, in that they both encapsulate an interface in a reference object. The key difference is that extension points are registered and provided by plugins themselves, and do not have any factory associated with them. Extension points for a given plugin are also only accessible to modules that extend that same plugin. @@ -42,7 +44,7 @@ class ActionsExtension implements ScaffolderActionsExtensionPoint { export const scaffolderPlugin = createBackendPlugin( { - id: 'scaffolder', + pluginId: 'scaffolder', register(env) { const actionsExtensions = new ActionsExtension(); env.registerExtensionPoint( diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 83428c7a26..2f359eaa75 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -6,6 +6,8 @@ sidebar_label: Modules description: Modules for backend plugins --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Backend modules are used to extend [plugins](./04-plugins.md) with additional features or change existing behavior. They must always be installed in the same backend instance as the plugin that they extend, and may only extend a single plugin. Modules interact with their target plugin using the [extension points](./05-extension-points.md) registered by the plugin, while also being able to depend on the [services](./03-services.md) of that plugin. Both modules and plugins register an `init` method that is called during startup. In order to ensure that modules have registered all their extensions before the plugin starts up, all modules for each plugin are completely initialized before the plugin itself is initialized. In practice this means that all promises returned by each `init` method of the modules need to resolve before the plugin `init` method is called. This also means that it is not possible to further interact with the extension points once the `init` method has resolved. diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index 6bd7c412c3..b62e049f08 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -6,6 +6,8 @@ sidebar_label: Naming Patterns description: Naming patterns in the backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports. ### Plugins @@ -19,7 +21,7 @@ Example: ```ts export const catalogPlugin = createBackendPlugin({ - id: 'catalog', + pluginId: 'catalog', ... }) ``` @@ -34,7 +36,7 @@ export const catalogPlugin = createBackendPlugin({ Example: ```ts -export const catalogModuleGithubEntityProvider = createBackendPlugin({ +export const catalogModuleGithubEntityProvider = createBackendModule({ pluginId: 'catalog', moduleId: 'githubEntityProvider', ... @@ -64,12 +66,12 @@ export const catalogProcessingExtensionPoint = createExtensionPointService` | `LoggerService`, `DatabaseService` | -| Reference | `ServiceRef` | `loggerServiceRef`, `databaseServiceRef` | -| ID | `.` | `'core.rootHttpRouter'`, `'catalog.catalogClient'` | -| Factory | `Factory` | `loggerFactory`, `databaseFactory` | +| Description | Pattern | Examples | +| ----------- | ---------------------- | -------------------------------------------------- | +| Interface | `Service` | `LoggerService`, `DatabaseService` | +| Reference | `ServiceRef` | `loggerServiceRef`, `databaseServiceRef` | +| ID | `.` | `'core.rootHttpRouter'`, `'catalog.catalogClient'` | +| Factory | `ServiceFactory` | `loggerServiceFactory`, `databaseServiceFactory` | Example: @@ -83,7 +85,7 @@ export const catalogClientServiceRef = createServiceRef({ ... }) -export const catalogClientFactory = createServiceFactory({ +export const catalogClientServiceFactory = createServiceFactory({ service: catalogClientServiceRef, ... }) diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index f810417ed7..bda2aa7eaa 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Overview description: Building backends using the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + > NOTE: If you have an existing backend that is not yet using the new backend > system, see [migrating](./08-migrating.md). @@ -59,11 +61,11 @@ All of these services can be replaced with your own implementations if you need For example, let's say we want to customize the core configuration service to enable remote configuration loading. That would look something like this: ```ts -import { configFactory } from '@backstage/backend-app-api'; +import { configServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configFactory({ + configServiceFactory({ remote: { reloadIntervalSeconds: 60 }, }), ], @@ -158,11 +160,11 @@ A shared environment is defined using `createSharedEnvironment`. In this example ```ts // packages/backend-env/src/index.ts import { createSharedEnvironment } from '@backstage/backend-plugin-api'; -import { customDiscoveryFactory } from './customDiscoveryFactory'; +import { customDiscoveryServiceFactory } from './customDiscoveryServiceFactory'; export const env = createSharedEnvironment({ services: [ - customDiscoveryFactory(), // custom DiscoveryService implementation + customDiscoveryServiceFactory(), // custom DiscoveryService implementation ], }); ``` diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 6e0b84b10f..e503d627ef 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -6,6 +6,8 @@ sidebar_label: Migration Guide description: How to migrate existing backends to the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + ## Overview This section describes how to migrate an existing Backstage backend service diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 01e35036aa..cae5052d04 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Overview description: Building backend plugins and modules using the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + > NOTE: If you have an existing backend and/or backend plugins that are not yet > using the new backend system, see [migrating](./08-migrating.md). @@ -34,7 +36,7 @@ import { import { createExampleRouter } from './router'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -181,7 +183,7 @@ that needs to be different across environments. import { coreServices } from '@backstage/backend-plugin-api'; export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { config: coreServices.config }, @@ -214,7 +216,7 @@ export interface ExampleOptions { export const examplePlugin = createBackendPlugin( (options?: ExampleOptions) => ({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index 20bef6fec4..37c5698512 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -6,6 +6,8 @@ sidebar_label: Testing description: Learn how to test your backend plugins and modules --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Utilities for testing backend plugins and modules are available in `@backstage/backend-test-utils`. This section describes those facilities. diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index ec003a6fec..687f4c1d5e 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -6,6 +6,8 @@ sidebar_label: Migration Guide description: How to migrate existing backend plugins to the new backend system --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + Migrating an existing backend plugin to the new backend system is fairly straightforward. The process is similar across the majority of plugins which just return a `Router` that is then wired up in the `index.ts` file of your backend. The primary thing that we need to do is to make sure that the dependencies that are required by the plugin are available, and then registering the router with the HTTP router service. Let's look at an example of migrating the Kubernetes backend plugin. In the existing (old) system, the kubernetes backend is structured like this: @@ -44,7 +46,7 @@ import { Router } from 'express'; import { KubernetesBuilder } from './KubernetesBuilder'; export const kubernetesPlugin = createBackendPlugin({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { env.registerInit({ deps: { @@ -93,7 +95,7 @@ export interface KubernetesOptions { } const kubernetesPlugin = createBackendPlugin((options: KubernetesOptions) => ({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { env.registerInit({ deps: { @@ -180,7 +182,7 @@ class ClusterSupplier implements KubernetesClusterSupplierExtensionPoint { } export const kubernetesPlugin = createBackendPlugin({ - id: 'kubernetes', + pluginId: 'kubernetes', register(env) { const extensionPoint = new ClusterSupplier(); // We register the extension point with the backend, which allows modules to diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index 4ef9d75bde..b6682c2708 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -6,6 +6,8 @@ sidebar_label: Core Services description: Core backend service APIs --- +> **DISCLAIMER: The new backend system is under active development and is not considered stable** + The default backend provides several [core services](https://github.com/backstage/backstage/blob/master/packages/backend-plugin-api/src/services/definitions/coreServices.ts) out of the box which includes access to configuration, logging, URL Readers, databases and more. All core services are available through the `coreServices` namespace in the `@backstage/backend-plugin-api` package. @@ -31,7 +33,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { http: coreServices.httpRouter }, @@ -57,11 +59,11 @@ There's additional configuration that you can optionally pass to setup the `http You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { httpRouterFactory } from '@backstage/backend-app-api'; +import { httpRouterServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - httpRouterFactory({ + httpRouterServiceFactory({ getPath: (pluginId: string) => `/plugins/${pluginId}`, }), ], @@ -84,7 +86,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -114,11 +116,11 @@ There's additional options that you can pass to configure the root HTTP Router s You can configure the root HTTP Router service by passing the options to the `createBackend` function. ```ts -import { rootHttpRouterFactory } from '@backstage/backend-app-api'; +import { rootHttpRouterServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - rootHttpRouterFactory({ + rootHttpRouterServiceFactory({ configure: ({ app, middleware, routes, config, logger, lifecycle }) => { // the built in middleware is provided through an option in the configure function app.use(middleware.helmet()); @@ -155,7 +157,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -181,11 +183,11 @@ There's additional configuration that you can optionally pass to setup the `conf You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { configFactory } from '@backstage/backend-app-api'; +import { configServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - configFactory({ + configServiceFactory({ argv: [ '--config', '/backstage/app-config.development.yaml', @@ -213,7 +215,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -286,7 +288,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -325,7 +327,7 @@ import { import { resolvePackagePath } from '@backstage/backend-common'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -364,7 +366,7 @@ import { import { fetch } from 'node-fetch'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -395,7 +397,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -436,11 +438,11 @@ There's additional configuration that you can optionally pass to setup the `iden You can configure these additional options by adding an override for the core service when calling `createBackend` like follows: ```ts -import { identityFactory } from '@backstage/backend-app-api'; +import { identityServiceFactory } from '@backstage/backend-app-api'; const backend = createBackend({ services: [ - identityFactory({ + identityServiceFactory({ issuer: 'backstage', algorithms: ['ES256', 'RS256'], }), @@ -463,7 +465,7 @@ import { } from '@backstage/backend-plugin-api'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -477,10 +479,7 @@ createBackendPlugin({ // do some other stuff. }, 1000); - lifecycle.addShutdownHook({ - fn: () => clearInterval(interval), - logger, - }); + lifecycle.addShutdownHook(() => clearInterval(interval)); }, }); }, @@ -497,17 +496,19 @@ The following example shows how to override the default implementation of the li ```ts class MyCustomLifecycleService implements RootLifecycleService { - constructor(private readonly logger: LoggerService) { - ['SIGKILL', 'SIGTERM'].map(signal => - process.on(signal, () => this.shutdown()), - ); - } + constructor(private readonly logger: LoggerService) {} #isCalled = false; - #shutdownTasks: Array = []; + #shutdownTasks: Array<{ + hook: LifecycleServiceShutdownHook; + options?: LifecycleServiceShutdownOptions; + }> = []; - addShutdownHook(options: LifecycleServiceShutdownHook): void { - this.#shutdownTasks.push(options); + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + this.#shutdownTasks.push({ hook, options }); } async shutdown(): Promise { @@ -518,10 +519,10 @@ class MyCustomLifecycleService implements RootLifecycleService { this.logger.info(`Running ${this.#shutdownTasks.length} shutdown tasks...`); await Promise.all( - this.#shutdownTasks.map(async hook => { - const { logger = this.logger } = hook; + this.#shutdownTasks.map(async ({ hook, options }) => { + const logger = options?.logger ?? this.logger; try { - await hook.fn(); + await hook(); logger.info(`Shutdown hook succeeded`); } catch (error) { logger.error(`Shutdown hook failed, ${error}`); @@ -562,7 +563,7 @@ import { import { Router } from 'express'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -611,7 +612,7 @@ import { import { fetch } from 'node-fetch'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { @@ -650,7 +651,7 @@ import { import os from 'os'; createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env) { env.registerInit({ deps: { diff --git a/docs/features/kubernetes/proxy.md b/docs/features/kubernetes/proxy.md new file mode 100644 index 0000000000..5848d62e3e --- /dev/null +++ b/docs/features/kubernetes/proxy.md @@ -0,0 +1,87 @@ +--- +id: proxy +title: Kubernetes Backend Proxy Endpoint +sidebar_label: Proxy +description: Interacting with the Kubernetes API in Backstage plugins +--- + +[Contributors](https://backstage.io/docs/overview/glossary#backstage-user-profiles) wanting to +create developer portal experiences based on data from Kubernetes (e.g. for +interacting with [Custom +Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/) +beyond the default behaviors of the existing Kubernetes plugin) can leverage the +Kubernetes backend plugin's proxy endpoint to allow them to make arbitrary +requests to the [REST +API](https://kubernetes.io/docs/reference/using-api/api-concepts/). + +Here is a snippet fetching namespaces from a cluster configured with the +`google` [auth provider](https://backstage.io/docs/features/kubernetes/configuration#clustersauthprovider): + +```typescript +import { + discoveryApiRef, + googleAuthApiRef, + useApi, +} from '@backstage/core-plugin-api'; + +const CLUSTER_NAME = ''; // use a known cluster name + +// get a bearer token from Google +const googleAuthApi = useApi(googleAuthApiRef); +const token = await googleAuthApi.getAccessToken( + 'https://www.googleapis.com/auth/cloud-platform', +); + +const discoveryApi = useApi(discoveryApiRef); +const kubernetesBaseUrl = await discoveryApi.getBaseUrl('kubernetes'); +const kubernetesProxyEndpoint = `${kubernetesBaseUrl}/proxy`; + +// fetch namespaces +await fetch(`${kubernetesProxyEndpoint}/api/v1/namespaces`, { + method: 'GET', + headers: { + 'X-Kubernetes-Cluster': CLUSTER_NAME, + Authorization: `Bearer ${token}`, + }, +}); +``` + +## How it works + +The proxy will interpret the +[`X-Kubernetes-Cluster` +header](https://backstage.io/docs/reference/plugin-kubernetes-backend.header_kubernetes_cluster) +as the name of the cluster to target. This name will be compared to each cluster +returned by all the configured [cluster +locators](https://backstage.io/docs/features/kubernetes/configuration#clusterlocatormethods) +-- the first cluster whose [`name` field](https://backstage.io/docs/features/kubernetes/configuration#clustersname) matches +the value in the header will be targeted. + +Then the request will be forwarded verbatim (but with the endpoint's base URL +prefix stripped) to the cluster. + +## Authentication + +Until some security and permission decisions are made (see [this +conversation](https://github.com/backstage/backstage/pull/13026/files#r1029376939) +for context), contributors consuming the proxy endpoint in their plugin code are +responsible for negotiating their own bearer token out-of-band. This requires +knowing some auth details about the cluster being contacted -- in practice, only +clusters with [client side auth +providers](https://backstage.io/docs/features/kubernetes/authentication#client-side-providers) can reasonably be reached. + +The proxy has no provisions for mTLS, so it cannot be used to connect to +clusters using the [x509 Client +Certs](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) +authentication strategy. [Bearer +tokens](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#putting-a-bearer-token-in-a-request) +will be forwarded as-is. + +## Other known limitations + +The proxy as it was released in [Backstage +1.9](https://github.com/backstage/backstage/blob/master/docs/releases/v1.9.0-changelog.md#patch-changes-15) +has a known bug: + +- [#15901](https://github.com/backstage/backstage/issues/15901) - it cannot + reliably target clusters who share the same name with another located cluster. diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 6f113630f6..b464168724 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -235,6 +235,20 @@ export const YourSearchResultListItemExtension = plugin.provide( ); ``` +If your list item accept props, you can extend the `SearchResultListItemExtensionProps` with your component specific props: + +```tsx +export const YourSearchResultListItemExtension: ( + props: SearchResultListItemExtensionProps, +) => JSX.Element | null = plugin.provide( + createSearchResultListItemExtension({ + name: 'YourSearchResultListItem', + component: () => + import('./components').then(m => m.YourSearchResultListItem), + }), +); +``` + Additionally, you can define a predicate function that receives a result and returns whether your extension should be used to render it or not: ```tsx diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index da4eb3d229..5fc2537712 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -89,23 +89,23 @@ export class FrobsProvider implements EntityProvider { private readonly reader: UrlReader; private connection?: EntityProviderConnection; - /** [1] **/ + /** [1] */ constructor(env: string, reader: UrlReader) { this.env = env; this.reader = reader; } - /** [2] **/ + /** [2] */ getProviderName(): string { return `frobs-${this.env}`; } - /** [3] **/ + /** [3] */ async connect(connection: EntityProviderConnection): Promise { this.connection = connection; } - /** [4] **/ + /** [4] */ async run(): Promise { if (!this.connection) { throw new Error('Not initialized'); @@ -116,10 +116,10 @@ export class FrobsProvider implements EntityProvider { ); const data = JSON.parse(await response.buffer()).toString(); - /** [5] **/ + /** [5] */ const entities: Entity[] = frobsToEntities(data); - /** [6] **/ + /** [6] */ await this.connection.applyMutation({ type: 'full', entities: entities.map(entity => ({ diff --git a/docs/features/software-catalog/system-model.md b/docs/features/software-catalog/system-model.md index 409f3e8450..16ad48abcf 100644 --- a/docs/features/software-catalog/system-model.md +++ b/docs/features/software-catalog/system-model.md @@ -63,6 +63,17 @@ BigTable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with components and systems will better allow us to visualize resource footprint, and create tooling around them. +##Organizational Entities + +### User + +A user describes a person, such as an employee, a contractor, or similar. + +### Group + +A group describes an organizational entity, such as for example a team, a +business unit, or a loose collection of people in an interest group. + ## Ecosystem Modeling A large catalogue of components, APIs and resources can be highly granular and @@ -108,3 +119,19 @@ domain would come with some documentation on how to accept payments for a new product or use-case, share the same entity types in their APIs, and integrate well with each other. Other domains could be “Content Ingestion”, “Ads” or “Search”. + +##Other + +### Location + +A location is a marker that references other places to look for catalog data. + +### Type + +The type field in the system has no set meaning. It is up to the user to assign their own types and use them as desired, such as for link validation or creating custom UI components. Some common pre-defined types are depicted in the ecosystem modeling diagram. + +### Template + +A template definition describes both the parameters that are rendered in the +frontend part of the scaffolding wizard, and the steps that are executed when +scaffolding that component. diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index dfbd4b0a42..ffe3312501 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -168,5 +168,6 @@ scaffolder backend: | Scaffolder Git Actions | [plugin-scaffolder-git-actions](https://www.npmjs.com/package/@mdude2314/backstage-plugin-scaffolder-git-actions) | [Drew Hill](https://github.com/arhill05) | | Azure Pipeline Actions | [scaffolder-backend-module-azure-pipelines](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-pipelines) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | | Azure Repository Actions | [scaffolder-backend-module-azure-repositories](https://www.npmjs.com/package/@parfuemerie-douglas/scaffolder-backend-module-azure-repositories) | [Parfümerie Douglas](https://github.com/Parfuemerie-Douglas) | +| Snyk Import Project | [plugin-scaffolder-backend-module-snyk](https://www.npmjs.com/package/@ma11hewthomas/plugin-scaffolder-backend-module-snyk) | [Matthew Thomas](https://github.com/Ma11hewThomas) | Have fun! 🚀 diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 71aa0ab758..a272f05f3f 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -112,11 +112,11 @@ steps which would be rendered as different steps in the scaffolder plugin frontend. Each `Step` is `JSONSchema` with some extra goodies for styling what it might -look like in the frontend. For these steps we rely very heavily on this library: -https://github.com/rjsf-team/react-jsonschema-form. They have some great docs -too here: https://react-jsonschema-form.readthedocs.io/ and a playground where -you can play around with some examples here -https://rjsf-team.github.io/react-jsonschema-form. +look like in the frontend. For these steps we rely very heavily on this +[library](https://github.com/rjsf-team/react-jsonschema-form). They have some +[great docs](https://rjsf-team.github.io/react-jsonschema-form/docs/) and a +[playground](https://rjsf-team.github.io/react-jsonschema-form) where you can +play around with some examples. There's another option for that library called `uiSchema` which we've taken advantage of, and we've merged it with the existing `JSONSchema` that you diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index fe1058b2ca..60999f599c 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -125,6 +125,7 @@ discover available Addons, we've compiled a list of them here: | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.expandablenavigation) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.lightbox) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. | Got an Addon to contribute? Feel free to add a row above! diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md index c2070e7840..578a631798 100644 --- a/docs/features/techdocs/getting-started.md +++ b/docs/features/techdocs/getting-started.md @@ -262,12 +262,12 @@ You will have to install the `mkdocs` and `mkdocs-techdocs-core` package from pip, as well as `graphviz` and `plantuml` from your OS package manager (e.g. apt). -You can do so by including the following lines in the last step of your +You can do so by including the following lines right above `USER node` of your `Dockerfile`: ```Dockerfile RUN apt-get update && apt-get install -y python3 python3-pip -RUN pip3 install mkdocs-techdocs-core==1.0.1 +RUN pip3 install mkdocs-techdocs-core==1.1.7 ``` Please be aware that the version requirement could change, you need to check our diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index 3b3e3dd5ed..1fc476f418 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -28,3 +28,5 @@ The configuration is a structure with two elements: - `host`: The DevOps host; only `dev.azure.com` is supported. - `token` (optional): A personal access token as expected by Azure DevOps. + +> Note: The token should just be provided as the raw token generated by Azure DevOps using the format `raw_token` with no base64 encoding. Formatting and base64'ing is handled by dependent libraries handling the Azure DevOps API diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index dc0b911b3d..5a4dc8abdd 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -22,9 +22,9 @@ catalog: yourProviderId: host: gitlab-host # Identifies one of the hosts set up in the integrations branch: main # Optional. Uses `master` as default - group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole project will be scanned + group: example-group # Optional. Group and subgroup (if needed) to look for repositories. If not present the whole instance will be scanned entityFilename: catalog-info.yaml # Optional. Defaults to `catalog-info.yaml` - projectPattern: /[\s\S]*/ # Optional. Filters found projects based on provided patter. Defaults to `/[\s\S]*/`, what means to not filter anything + projectPattern: '[\s\S]*' # Optional. Filters found projects based on provided patter. Defaults to `[\s\S]*`, which means to not filter anything schedule: # optional; same options as in TaskScheduleDefinition # supports cron, ISO duration, "human duration" as used in code frequency: { minutes: 30 } diff --git a/docs/permissions/overview.md b/docs/permissions/overview.md index b972814aeb..693f848c82 100644 --- a/docs/permissions/overview.md +++ b/docs/permissions/overview.md @@ -34,6 +34,8 @@ The permission framework was designed with a few key properties in mind: 4. An authorization decision is sent to the plugin from the permission backend. +5. The user is either granted access or an error is shown. The plugin is responsible for implementing a response to the user. + ## How do I get started? See the "[getting started](./getting-started.md)" permission documentation for Backstage integrators. diff --git a/docs/permissions/plugin-authors/01-setup.md b/docs/permissions/plugin-authors/01-setup.md index 18de410612..a38b81e679 100644 --- a/docs/permissions/plugin-authors/01-setup.md +++ b/docs/permissions/plugin-authors/01-setup.md @@ -26,6 +26,9 @@ The source code is available here: git checkout master -- plugins/example-todo-list/ git checkout master -- plugins/example-todo-list-backend/ git checkout master -- plugins/example-todo-list-common/ + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list/package.json + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-backend/package.json + sed -i '' 's/workspace:\^/\*/g' plugins/example-todo-list-common/package.json for file in plugins/*; do mv "$file" "$OLDPWD/${file/example-todo/todo}"; done cd - ``` @@ -37,15 +40,15 @@ The source code is available here: 2. Add these packages as dependencies for your Backstage app: ``` - $ yarn workspace backend add @internal/plugin-todo-list-backend@^1.0.0 @internal/plugin-todo-list-common@^1.0.0 - $ yarn workspace app add @internal/plugin-todo-list@^1.0.0 + $ yarn workspace backend add @internal/plugin-todo-list-backend @internal/plugin-todo-list-common + $ yarn workspace app add @internal/plugin-todo-list ``` 3. Include the backend and frontend plugin in your application: Create a new `packages/backend/src/plugins/todolist.ts` with the following content: - ```javascript + ```typescript import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; import { createRouter } from '@internal/plugin-todo-list-backend'; import { Router } from 'express'; diff --git a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md index 241b175987..2ceb8057f4 100644 --- a/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md +++ b/docs/permissions/plugin-authors/02-adding-a-basic-permission-check.md @@ -146,7 +146,7 @@ In order to test the logic above, the integrators of your backstage instance nee - async handle(): Promise { + async handle( + request: PolicyQuery, -+ user?: BackstageIdentityResponse, ++ _user?: BackstageIdentityResponse, + ): Promise { + if (isPermission(request.permission, todoListCreatePermission)) { + return { @@ -204,7 +204,7 @@ First we'll clean up the `plugins/todo-list-backend/src/service/router.test.ts`: const router = await createRouter({ logger: getVoidLogger(), identity: {} as DefaultIdentityClient, -+ permissions: toPermissionEvaluator, ++ permissions: permissionEvaluator, }); app = express().use(router); }); @@ -235,7 +235,7 @@ Then we want to update the `plugins/todo-list-backend/src/service/standaloneServ + ServerTokenManager, } from '@backstage/backend-common'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; - import { ServerPermissionClient } from '@backstage/plugin-permission-node'; ++ import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; @@ -285,4 +285,44 @@ Then we want to update the `plugins/todo-list-backend/src/service/standaloneServ module.hot?.accept(); ``` +Finally, we need to update `plugins/todo-list-backend/src/plugin.ts`: + +```diff + import { loggerToWinstonLogger } from '@backstage/backend-common'; + import { + coreServices, + createBackendPlugin, + } from '@backstage/backend-plugin-api'; + import { createRouter } from './service/router'; + + /** + * The example TODO list backend plugin. + * + * @alpha + */ + export const exampleTodoListPlugin = createBackendPlugin({ + pluginId: 'exampleTodoList', + register(env) { + env.registerInit({ + deps: { + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, ++ permissions: coreServices.permissions, + }, +- async init({ identity, logger, httpRouter }) { ++ async init({ identity, logger, httpRouter, permissions }) { + httpRouter.use( + await createRouter({ + identity, + logger: loggerToWinstonLogger(logger), + permissions, + }), + ); + }, + }); + }, + }); +``` + Now when you run `yarn tsc` you should have no more errors. diff --git a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md index 8913b6d438..b063727c71 100644 --- a/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md +++ b/docs/permissions/plugin-authors/03-adding-a-resource-permission-check.md @@ -76,7 +76,7 @@ This enables decisions based on characteristics of the resource, but it's import Install the missing module: ``` -$ yarn workspace @internal/plugin-todo-list-backend add @backstage/plugin-permission-node +$ yarn workspace @internal/plugin-todo-list-backend add @backstage/plugin-permission-node zod ``` Create a new `plugins/todo-list-backend/src/service/rules.ts` file and append the following code: @@ -89,7 +89,8 @@ import { Todo, TodoFilter } from './todos'; export const createTodoListPermissionRule = makeCreatePermissionRule< Todo, - TodoFilter + TodoFilter, + typeof TODO_LIST_RESOURCE_TYPE >(); export const isOwner = createTodoListPermissionRule({ @@ -97,8 +98,8 @@ export const isOwner = createTodoListPermissionRule({ description: 'Should allow only if the todo belongs to the user', resourceType: TODO_LIST_RESOURCE_TYPE, paramsSchema: z.object({ - userId: z.string().describe('User ID to match on the resource') - }) + userId: z.string().describe('User ID to match on the resource'), + }), apply: (resource: Todo, { userId }) => { return resource.author === userId; }, @@ -187,6 +188,7 @@ Make sure `todoListConditions` and `createTodoListConditionalDecision` are expor ```diff export * from './service/router'; + export * from './conditionExports'; + export { exampleTodoListPlugin } from './plugin'; ``` ## Test the authorized update endpoint @@ -209,7 +211,6 @@ Let's go back to the permission policy's handle function and try to authorize ou + import { + todoListCreatePermission, + todoListUpdatePermission, -+ TODO_LIST_RESOURCE_TYPE, + } from '@internal/plugin-todo-list-common'; + import { + todoListConditions, @@ -217,7 +218,11 @@ Let's go back to the permission policy's handle function and try to authorize ou + } from '@internal/plugin-todo-list-backend'; ... - + async handle( + request: PolicyQuery, +- _user?: BackstageIdentityResponse, ++ user?: BackstageIdentityResponse, + ): Promise { if (isPermission(request.permission, todoListCreatePermission)) { return { result: AuthorizeResult.ALLOW, @@ -236,6 +241,7 @@ Let's go back to the permission policy's handle function and try to authorize ou return { result: AuthorizeResult.ALLOW, }; + } ``` For any incoming update requests, we now return a _Conditional Decision_. We are saying: diff --git a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md index 8ddcffdcd9..e84f53f176 100644 --- a/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md +++ b/docs/permissions/plugin-authors/04-authorizing-access-to-paginated-data.md @@ -15,7 +15,7 @@ One possible solution may leverage the batching functionality to authorize all o - res.json(getAll()) + const items = getAll(); + const decisions = await permissions.authorize( -+ items.map(({ id }) => ({ permission: todosListRead, resourceRef: id })), ++ items.map(({ id }) => ({ permission: todoListReadPermission, resourceRef: id })), + ); + const filteredItems = decisions.filter( @@ -53,7 +53,7 @@ Let's add another permission to the plugin. resourceType: TODO_LIST_RESOURCE_TYPE, }); + -+ export const todosListRead = createPermission({ ++ export const todoListReadPermission = createPermission({ + name: 'todos.list.read', + attributes: { action: 'read' }, + resourceType: TODO_LIST_RESOURCE_TYPE, @@ -81,10 +81,9 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev import { todosListCreate, todosListUpdate, -+ todosListRead, ++ todoListReadPermission, TODO_LIST_RESOURCE_TYPE, } from './permissions'; -+ import { rules } from './rules'; + const transformConditions: ConditionTransformer = createConditionTransformer(Object.values(rules)); @@ -95,7 +94,7 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev + ); + + const decision = ( -+ await permissions.authorizeConditional([{ permission: todosListRead }], { ++ await permissions.authorizeConditional([{ permission: todoListReadPermission }], { + token, + }) + )[0]; @@ -110,7 +109,6 @@ So far we've only used the `PermissionEvaluator.authorize` method, which will ev + } else { + res.json(getAll()); + } -+ } - res.json(getAll()); }); ``` @@ -121,7 +119,7 @@ Since `TodoFilter` used in our plugin matches the structure of the conditions ob ## Test the authorized read endpoint -Let's update our permission policy to return a conditional result whenever a `todosListRead` permission is received. In this case, we can reuse the decision returned for the `todosListCreate` permission. +Let's update our permission policy to return a conditional result whenever a `todoListReadPermission` permission is received. In this case, we can reuse the decision returned for the `todosListCreate` permission. ```diff // packages/backend/src/plugins/permission.ts @@ -132,7 +130,6 @@ import { todoListCreatePermission, todoListUpdatePermission, + todoListReadPermission, - TODO_LIST_RESOURCE_TYPE, } from '@internal/plugin-todo-list-common'; ... diff --git a/docs/permissions/plugin-authors/05-frontend-authorization.md b/docs/permissions/plugin-authors/05-frontend-authorization.md index d494ea60ba..753ce56461 100644 --- a/docs/permissions/plugin-authors/05-frontend-authorization.md +++ b/docs/permissions/plugin-authors/05-frontend-authorization.md @@ -56,7 +56,11 @@ Let's make the following changes in `plugins/todo-list/src/components/TodoListPa - Add - + {!loadingPermission && ( -+ + )} @@ -118,7 +122,10 @@ Providing a disabled state can be a helpful signal to users, but there may be ca - - - -+ }> ++ } ++ > + + + @@ -149,11 +156,15 @@ Providing a disabled state can be a helpful signal to users, but there may be ca onChange={e => (title.current = e.target.value)} /> - {!loadingPermission && ( -- - )} -+ diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index bfc6f79661..785d364ae2 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -84,7 +84,7 @@ import { // export type ExamplePluginOptions = { exampleOption: boolean }; export const examplePlugin = createBackendPlugin({ // unique id for the plugin - id: 'example', + pluginId: 'example', // It's possible to provide options to the plugin // register(env, options: ExamplePluginOptions) { register(env) { @@ -111,7 +111,7 @@ If we wanted our plugin to accept options as well, we'd accept the options as th ```ts export const examplePlugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(env, options?: { silent?: boolean }) { env.registerInit({ deps: { logger: coreServices.logger }, diff --git a/docs/plugins/url-reader.md b/docs/plugins/url-reader.md index 595c87ab94..fa9c341543 100644 --- a/docs/plugins/url-reader.md +++ b/docs/plugins/url-reader.md @@ -40,7 +40,7 @@ i.e.`packages/backend/src/index.ts`. ```ts // File: packages/backend/src/index.ts -import { URLReaders } from '@backstage/backend-common'; +import { UrlReaders } from '@backstage/backend-common'; function makeCreateEnv(config: Config) { // .... diff --git a/docs/releases/v1.11.0-next.1-changelog.md b/docs/releases/v1.11.0-next.1-changelog.md new file mode 100644 index 0000000000..aa9c447149 --- /dev/null +++ b/docs/releases/v1.11.0-next.1-changelog.md @@ -0,0 +1,2164 @@ +# Release v1.11.0-next.1 + +## @backstage/plugin-catalog@1.8.0-next.1 + +### Minor Changes + +- 0c1fc3986c: Added Markdown support in the `AboutCard` description section +- 0eaa579f89: The `CatalogSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-react@1.3.0-next.1 + +### Minor Changes + +- fab93c2fe8: Aligned buttons on "Unregister entity" dialog to keep them on the same line + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/plugin-explore@0.4.0-next.1 + +### Minor Changes + +- 0eaa579f89: The `ToolSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-scaffolder-backend@1.11.0-next.1 + +### Minor Changes + +- 127154930f: Renamed the export `scaffolderCatalogModule` to `catalogModuleTemplateKind` in order to follow the new recommended naming patterns of backend system items. This is technically a breaking change but in an alpha export, so take care to change your imports if you have already migrated to the new backend system. + +### Patch Changes + +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + +## @backstage/plugin-search@1.1.0-next.1 + +### Minor Changes + +- 0eaa579f89: Update `SearchModal` component to use `SearchResult` extensions. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-react@1.5.0-next.0 + +### Minor Changes + +- 0eaa579f89: - Create the search results extensions, for more details see the documentation [here](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions); + - Update the `SearchResult`, `SearchResultList` and `SearchResultGroup` components to use extensions and default their props to optionally accept a query, when the query is not passed, the component tries to get it from the search context. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights-node@0.4.0-next.1 + +### Minor Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-techdocs@1.5.0-next.1 + +### Minor Changes + +- 20840b36b4: Update DocsTable and EntityListDocsTable to accept overrides for Material Table options. +- 0eaa579f89: The `TechDocsSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + +## @backstage/app-defaults@1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/backend-app-api@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-node@0.7.5-next.1 + +## @backstage/backend-common@0.18.2-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + +## @backstage/backend-plugin-api@0.3.2-next.1 + +### Patch Changes + +- ae88f61e00: The `register` methods passed to `createBackendPlugin` and `createBackendModule` + now have dedicated `BackendPluginRegistrationPoints` and + `BackendModuleRegistrationPoints` arguments, respectively. This lets us make it + clear on a type level that it's not possible to pass in extension points as + dependencies to plugins (should only ever be done for modules). This has no + practical effect on code that was already well behaved. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/backend-tasks@0.4.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + +## @backstage/cli@0.22.2-next.0 + +### Patch Changes + +- 561df21ea3: The `backstage-cli repo test` command now sets a default Jest `--workerIdleMemoryLimit` of 1GB. If needed to ensure that tests are not run in band, `--maxWorkers=2` is set as well. This is the recommended workaround for dealing with Jest workers leaking memory and eventually hitting the heap limit. +- 2815981057: Show module name causing error during build +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- 6d3abfded1: Switch to inline source maps for test transpilation, simplifying editor setups. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## @backstage/core-app-api@1.4.1-next.0 + +### Patch Changes + +- dff4d8ddb1: Fixed an issue where an explicit port the frontend base URL could break the app. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + +## @backstage/core-components@0.12.4-next.0 + +### Patch Changes + +- 910015f5b7: The Button component has been deprecated in favor of the LinkButton component +- 20840b36b4: Adds new type, TableOptions, extending Material Table Options. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + +## @backstage/create-app@0.4.37-next.1 + +### Patch Changes + +- 86a8dfd7b0: Added a check to ensure that Yarn v1 is used when creating new projects. +- 0eaa579f89: Update `SearchPage` template to use `SearchResult` extensions. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/dev-utils@1.0.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/app-defaults@1.1.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + +## @backstage/integration-react@1.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @techdocs/cli@1.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.1 + +## @backstage/test-utils@1.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/plugin-adr@0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-adr-backend@0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-airbrake@0.3.15-next.1 + +### Patch Changes + +- 41377156d0: Adds a boolean helper function to airbrake plugin for use on the EntityPage to show/hide airbrake tab depending on whether the entity's catalog-info.yml has an airbrake id set in the metadata +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/dev-utils@1.0.12-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-airbrake-backend@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + +## @backstage/plugin-allure@0.1.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-analytics-module-ga@0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apache-airflow@0.2.8-next.0 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-api-docs@0.8.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apollo-explorer@0.1.8-next.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-app-backend@0.3.42-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.17.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + +## @backstage/plugin-auth-node@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-azure-devops@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-devops-backend@0.3.21-next.1 + +### Patch Changes + +- cc926a59bd: Fixed a bug where the azure devops host in URLs on the readme card was being URL encoded, breaking hosts with ports. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-azure-sites-backend@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-badges-backend@0.1.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-bazaar-backend@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + +## @backstage/plugin-bitrise@0.1.42-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-catalog-backend@1.7.2-next.1 + +### Patch Changes + +- 2380506364: The process of adding or modifying fields in the software-catalog search index has been simplified. For more details, see [how to customize fields in the Software Catalog index](https://backstage.io/docs/features/search/how-to-guides#how-to-customize-fields-in-the-software-catalog-index). +- 9573651919: The previous migration that adds the `search.original_value` column may leave some of the entities not updated. Add a migration script to trigger a reprocessing of the entities. +- fc73f6aae5: Switched the order of reprocessing statements retroactively in migrations. This only improves the experience for those who at a later time perform a large upgrade of an old Backstage installation. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend-module-aws@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.13-next.1 + +### Patch Changes + +- 2890f47517: This will add the ability to use Azure DevOps with multi project with a single value which is a new feature as previously this had to be done manually for each project that you wanted to add. + + Right now you would have to fill in multiple values in the config to use multiple projects: + + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'firstProject' # this will match the firstProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + yourSecondProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'secondProject' # this will match the secondProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + + With this change you can actually have all projects available where your PAT determines which you have access to, so that includes multiple projects: + + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: '*' # this will match all projects where your PAT has access to + repository: '*' # this will match all repos + path: /catalog-info.yaml + +- 85b04f659a: Internal refactor to not use deprecated `substr` + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.9-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.2.5-next.1 + +### Patch Changes + +- 66158754b4: Add support for filtering out forks +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.13-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 52c5685ceb: Implement Group and User Catalog Provider +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.2.0-next.1 + +### Patch Changes + +- b7e36660d5: Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.4.8-next.1 + +### Patch Changes + +- 4c86436fdf: Fix MS Graph provider to use target URL for fetching access token +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + +## @backstage/plugin-catalog-graph@0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-catalog-import@0.9.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/plugin-catalog-common@1.0.11-next.0 + +## @backstage/plugin-catalog-node@1.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + +## @backstage/plugin-cicd-statistics@0.1.17-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.17-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-circleci@0.3.15-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-cloudbuild@0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-climate@0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-coverage@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-code-coverage-backend@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-codescene@0.1.10-next.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-config-schema@0.1.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@2.0.0-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-events-backend@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-aws-sqs@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-azure@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-github@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-module-gitlab@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-backend-test-utils@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.1 + +## @backstage/plugin-events-node@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + +## @backstage/plugin-explore-backend@0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-firehydrant@0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-fossa@0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcalendar@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcp-projects@0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-git-release-manager@0.3.28-next.0 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-actions@0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-deployments@0.1.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-issues@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-pull-requests-board@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gitops-profiles@0.3.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gocd@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphiql@0.2.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphql-backend@0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.0 + +## @backstage/plugin-home@0.4.31-next.1 + +### Patch Changes + +- 3d1d867d42: Fixed regression that caused the `WelcomeTitle` to not be the right size when passed to the `title` property of the `
    ` component. A Storybook entry was also added for the `WelcomeTitle` +- c553a625d2: remove unused plugin-stack-overflow dependency +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-ilert@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-jenkins@0.7.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-jenkins-common@0.1.13-next.0 + +## @backstage/plugin-jenkins-backend@0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-jenkins-common@0.1.13-next.0 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-kafka@0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-kafka-backend@0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-kubernetes@0.7.8-next.1 + +### Patch Changes + +- 145a79a15b: Condenses kubernetes ui plugin to fit more onscreen and increase visibility +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-kubernetes-common@0.6.0-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-kubernetes-backend@0.9.3-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-kubernetes-common@0.6.0-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + +## @backstage/plugin-kubernetes-common@0.6.0-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/catalog-model@1.1.6-next.0 + +## @backstage/plugin-lighthouse@0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic@0.3.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic-dashboard@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + +## @backstage/plugin-org@0.6.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-org-react@0.1.4-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-pagerduty@0.5.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-periskop@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-periskop-backend@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + +## @backstage/plugin-permission-backend@0.5.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + +## @backstage/plugin-permission-node@0.7.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-playlist@0.1.6-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-playlist-backend@0.2.5-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-proxy-backend@0.2.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + +## @backstage/plugin-rollbar@0.4.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-rollbar-backend@0.1.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder@1.11.0-next.1 + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- 0f0da2f256: Prefer schema ordering of template properties during review content generation. +- 38992bdbaf: Fixed bug in review step refactor that caused schema-based display settings for individual property values to be discarded. +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.2-next.1 + +### Patch Changes + +- da418c89e4: Fix broken module exports and dependencies to match a backend module, rather than a frontend plugin. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + +## @backstage/plugin-scaffolder-node@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + +## @backstage/plugin-scaffolder-react@1.1.0-next.1 + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + +## @backstage/plugin-search-backend@1.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-pg@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-node@1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-sentry@0.4.8-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-shortcuts@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.3-next.1 + +### Patch Changes + +- 6310eacc11: Additional export added in order to bind SonarQubeClient to its apiref +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-sonarqube-react@0.1.2-next.0 + +## @backstage/plugin-sonarqube-backend@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-splunk-on-call@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-stack-overflow@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-home@0.4.31-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-stack-overflow-backend@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights@0.3.7-next.1 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-insights-backend@0.5.8-next.1 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-tech-insights-common@0.2.10-next.0 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/types@1.0.2 + +## @backstage/plugin-tech-radar@0.6.1-next.0 + +### Patch Changes + +- 18024a231c: Allow to set additional links to the entry description. +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.10-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + +## @backstage/plugin-techdocs-backend@1.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + +## @backstage/plugin-techdocs-node@1.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-techdocs-react@1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + +## @backstage/plugin-todo@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-todo-backend@0.1.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-user-settings@0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-user-settings-backend@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + +## @backstage/plugin-vault@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-vault-backend@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-xcmetrics@0.2.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## example-app@0.2.80-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.1 + - @backstage/plugin-scaffolder@1.11.0-next.1 + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-tech-insights@0.3.7-next.1 + - @backstage/plugin-search@1.1.0-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.1 + - @backstage/plugin-dynatrace@2.0.0-next.1 + - @backstage/plugin-playlist@0.1.6-next.1 + - @backstage/plugin-home@0.4.31-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/plugin-kubernetes@0.7.8-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-tech-radar@0.6.1-next.0 + - @backstage/plugin-explore@0.4.0-next.1 + - @backstage/plugin-apache-airflow@0.2.8-next.0 + - @backstage/plugin-circleci@0.3.15-next.1 + - @backstage/plugin-sentry@0.4.8-next.1 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-airbrake@0.3.15-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/app-defaults@1.1.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-api-docs@0.8.15-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.1 + - @backstage/plugin-badges@0.2.39-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-graph@0.2.27-next.1 + - @backstage/plugin-catalog-import@0.9.5-next.1 + - @backstage/plugin-cloudbuild@0.3.15-next.1 + - @backstage/plugin-code-coverage@0.2.8-next.1 + - @backstage/plugin-cost-insights@0.12.4-next.1 + - @backstage/plugin-gcalendar@0.3.11-next.0 + - @backstage/plugin-gcp-projects@0.3.34-next.0 + - @backstage/plugin-github-actions@0.5.15-next.1 + - @backstage/plugin-gocd@0.1.21-next.1 + - @backstage/plugin-graphiql@0.2.47-next.0 + - @backstage/plugin-jenkins@0.7.14-next.1 + - @backstage/plugin-kafka@0.3.15-next.1 + - @backstage/plugin-lighthouse@0.3.15-next.1 + - @backstage/plugin-newrelic@0.3.33-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.1 + - @backstage/plugin-org@0.6.5-next.1 + - @backstage/plugin-pagerduty@0.5.8-next.1 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-rollbar@0.4.15-next.1 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.0 + - @backstage/plugin-stack-overflow@0.1.11-next.1 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + - @backstage/plugin-todo@0.2.17-next.1 + - @backstage/plugin-user-settings@0.6.3-next.1 + - @internal/plugin-catalog-customized@0.0.7-next.1 + +## example-backend@0.2.80-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/plugin-tech-insights-backend@0.5.8-next.1 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/plugin-azure-devops-backend@0.3.21-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/plugin-playlist-backend@0.2.5-next.1 + - example-app@0.2.80-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.1 + - @backstage/plugin-app-backend@0.3.42-next.1 + - @backstage/plugin-auth-backend@0.17.5-next.1 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-azure-sites-backend@0.1.4-next.1 + - @backstage/plugin-badges-backend@0.1.36-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-code-coverage-backend@0.2.8-next.1 + - @backstage/plugin-events-backend@0.2.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + - @backstage/plugin-explore-backend@0.0.4-next.1 + - @backstage/plugin-graphql-backend@0.1.32-next.1 + - @backstage/plugin-jenkins-backend@0.1.32-next.1 + - @backstage/plugin-kafka-backend@0.2.35-next.1 + - @backstage/plugin-permission-backend@0.5.17-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-proxy-backend@0.2.36-next.1 + - @backstage/plugin-rollbar-backend@0.1.39-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.1 + - @backstage/plugin-search-backend@1.2.3-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.1 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.1 + - @backstage/plugin-techdocs-backend@1.5.3-next.1 + - @backstage/plugin-todo-backend@0.1.39-next.1 + +## example-backend-next@0.0.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/backend-defaults@0.1.7-next.1 + - @backstage/plugin-app-backend@0.3.42-next.1 + +## techdocs-cli-embedded-app@0.2.79-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/app-defaults@1.1.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + +## @internal/plugin-catalog-customized@0.0.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + +## @internal/plugin-todo-list@1.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @internal/plugin-todo-list-backend@1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 diff --git a/docs/releases/v1.11.0-next.2-changelog.md b/docs/releases/v1.11.0-next.2-changelog.md new file mode 100644 index 0000000000..65f6622921 --- /dev/null +++ b/docs/releases/v1.11.0-next.2-changelog.md @@ -0,0 +1,2289 @@ +# Release v1.11.0-next.2 + +## @backstage/backend-app-api@0.4.0-next.2 + +### Minor Changes + +- 01a075ec1d: **BREAKING**: Renamed `RootHttpRouterConfigureOptions` to `RootHttpRouterConfigureContext`, and removed the unused type `ServiceOrExtensionPoint`. +- 4ae71b7f2e: **BREAKING** Renaming `*Factory` exports to `*ServiceFactory` instead. For example `configFactory` now is exported as `configServiceFactory`. +- d31d8e00b3: **BREAKING** `HttpServerCertificateOptions` when specified with a `key` and `cert` should also have the `type: 'pem'` instead of `type: 'plain'` + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- f60cca9da1: Updated database factory to pass service deps required for restoring database state during development. +- 610d65e143: Updates to match new `BackendFeature` type. +- ab22515647: The shutdown signal handlers are now installed as part of the backend instance rather than the lifecycle service, and explicitly cause the process to exit. +- b729f9f31f: Moved the options of the `config` and `rootHttpRouter` services out to the factories themselves, where they belong +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-dev-utils@0.1.0-next.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. + +## @backstage/backend-plugin-api@0.4.0-next.2 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/catalog-model@1.2.0-next.1 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/eslint-plugin@0.1.0-next.0 + +### Minor Changes + +- 179d301518: Added a new ESLint plugin with common rules for Backstage projects. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for more details. + +## @backstage/plugin-adr@0.4.0-next.2 + +### Minor Changes + +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-api-docs@0.9.0-next.2 + +### Minor Changes + +- 9ed53218a5: Adds a new tRPC API definition widget which users can utilize to integrate their tRPC API definitions into Backstage. + +### Patch Changes + +- 6856ab98f4: Updated dependency `@asyncapi/react-component` to `1.0.0-next.47`. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.0-next.2 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-entity-validation@0.1.0-next.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-graphql-voyager@0.1.0-next.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-lighthouse@0.4.0-next.2 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-lighthouse-backend@0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-lighthouse-common@0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder-react@1.1.0-next.2 + +### Minor Changes + +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-sentry@0.5.0-next.2 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/app-defaults@1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/backend-common@0.18.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` +- 0ff03319be: Updated usage of `createBackendPlugin`. +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-dev-utils@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/backend-defaults@0.1.7-next.2 + +### Patch Changes + +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + +## @backstage/backend-tasks@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/backend-test-utils@0.1.34-next.2 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/catalog-client@1.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/errors@1.1.4 + +## @backstage/cli@0.22.2-next.1 + +### Patch Changes + +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## @backstage/codemods@0.1.43-next.0 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/core-components@0.12.4-next.1 + +### Patch Changes + +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + +## @backstage/create-app@0.4.37-next.2 + +### Patch Changes + +- 02f1316e57: Updated `packages/app/cypress/.eslintrc.json` to remove the unnecessary `import/no-extraneous-dependencies` rule. +- Updated dependencies + - @backstage/cli-common@0.1.11 + +## @backstage/dev-utils@1.0.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/integration-react@1.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/repo-tools@0.1.2-next.0 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + +## @techdocs/cli@1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## @backstage/plugin-adr-backend@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-adr-common@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-airbrake@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/dev-utils@1.0.12-next.2 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-airbrake-backend@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-allure@0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-analytics-module-ga@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-apache-airflow@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-apollo-explorer@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-app-backend@0.3.42-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-backend@0.17.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-auth-node@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-azure-devops@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-azure-devops-backend@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## @backstage/plugin-azure-sites@0.1.4-next.2 + +### Patch Changes + +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-azure-sites-backend@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## @backstage/plugin-badges@0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-badges-backend@0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bazaar@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-bazaar-backend@0.2.5-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-bitrise@0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog@1.8.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend@1.7.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-backend-module-aws@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-azure@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-catalog-backend-module-github@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.13-next.2 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.2.0-next.2 + +### Patch Changes + +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-common@1.0.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-catalog-graph@0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-graphql@0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-catalog-import@0.9.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-catalog-node@1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## @backstage/plugin-catalog-react@1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + +## @backstage/plugin-cicd-statistics@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-cicd-statistics@0.1.17-next.2 + +## @backstage/plugin-circleci@0.3.15-next.2 + +### Patch Changes + +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-cloudbuild@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-climate@0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-coverage@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-code-coverage-backend@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-codescene@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-config-schema@0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-cost-insights@0.12.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.1 + +## @backstage/plugin-dynatrace@2.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-events-backend@0.2.3-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-aws-sqs@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-events-backend-module-azure@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-backend-module-github@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-module-gitlab@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-events-backend-test-utils@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.2 + +## @backstage/plugin-events-node@0.2.3-next.2 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + +## @backstage/plugin-explore@0.4.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-explore-backend@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-firehydrant@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-fossa@0.2.47-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-gcalendar@0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gcp-projects@0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-git-release-manager@0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## @backstage/plugin-github-actions@0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-deployments@0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-issues@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-github-pull-requests-board@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-gitops-profiles@0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-gocd@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-graphiql@0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-graphql-backend@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.1 + +## @backstage/plugin-home@0.4.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-ilert@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-jenkins@0.7.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + +## @backstage/plugin-jenkins-backend@0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-jenkins-common@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-kafka@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-kafka-backend@0.2.35-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-kubernetes@0.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## @backstage/plugin-kubernetes-backend@0.9.3-next.2 + +### Patch Changes + +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## @backstage/plugin-kubernetes-common@0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + +## @backstage/plugin-newrelic@0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-org@0.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-org-react@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-pagerduty@0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-periskop@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-periskop-backend@0.1.13-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-permission-backend@0.5.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-permission-node@0.7.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## @backstage/plugin-playlist@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-playlist-backend@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-playlist-common@0.1.4 + +## @backstage/plugin-proxy-backend@0.2.36-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-rollbar@0.4.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-rollbar-backend@0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## @backstage/plugin-scaffolder@1.11.0-next.2 + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-scaffolder-backend@1.11.0-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-common@1.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + +## @backstage/plugin-scaffolder-node@0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## @backstage/plugin-search@1.1.0-next.2 + +### Patch Changes + +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend@1.2.3-next.2 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-backend-node@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-search-react@1.5.0-next.1 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-shortcuts@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## @backstage/plugin-sonarqube@0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-sonarqube-react@0.1.2-next.1 + +## @backstage/plugin-sonarqube-backend@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-sonarqube-react@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + +## @backstage/plugin-splunk-on-call@0.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-stack-overflow@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-stack-overflow-backend@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-tech-insights@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## @backstage/plugin-tech-insights-backend@0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## @backstage/plugin-tech-insights-node@0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## @backstage/plugin-tech-radar@0.6.1-next.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @backstage/plugin-techdocs@1.5.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-backend@1.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @backstage/plugin-techdocs-node@1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## @backstage/plugin-techdocs-react@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + +## @backstage/plugin-todo@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-todo-backend@0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## @backstage/plugin-user-settings@0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-user-settings-backend@0.1.6-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## @backstage/plugin-vault@0.1.9-next.2 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @backstage/plugin-vault-backend@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## @backstage/plugin-xcmetrics@0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## example-app@0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/plugin-scaffolder@1.11.0-next.2 + - @backstage/cli@0.22.2-next.1 + - @backstage/plugin-api-docs@0.9.0-next.2 + - @backstage/plugin-tech-radar@0.6.1-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-explore@0.4.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/plugin-sentry@0.5.0-next.2 + - @backstage/plugin-circleci@0.3.15-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.2 + - @backstage/plugin-search@1.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.0-next.2 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.15-next.2 + - @backstage/plugin-apache-airflow@0.2.8-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.2 + - @backstage/plugin-badges@0.2.39-next.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-graph@0.2.27-next.2 + - @backstage/plugin-catalog-import@0.9.5-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cloudbuild@0.3.15-next.2 + - @backstage/plugin-code-coverage@0.2.8-next.2 + - @backstage/plugin-cost-insights@0.12.4-next.2 + - @backstage/plugin-dynatrace@2.0.0-next.2 + - @backstage/plugin-gcalendar@0.3.11-next.1 + - @backstage/plugin-gcp-projects@0.3.34-next.1 + - @backstage/plugin-github-actions@0.5.15-next.2 + - @backstage/plugin-gocd@0.1.21-next.2 + - @backstage/plugin-graphiql@0.2.47-next.1 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-jenkins@0.7.14-next.2 + - @backstage/plugin-kafka@0.3.15-next.2 + - @backstage/plugin-kubernetes@0.7.8-next.2 + - @backstage/plugin-newrelic@0.3.33-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + - @backstage/plugin-org@0.6.5-next.2 + - @backstage/plugin-pagerduty@0.5.8-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist@0.1.6-next.2 + - @backstage/plugin-rollbar@0.4.15-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.1 + - @backstage/plugin-stack-overflow@0.1.11-next.2 + - @backstage/plugin-tech-insights@0.3.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + - @backstage/plugin-todo@0.2.17-next.2 + - @backstage/plugin-user-settings@0.6.3-next.2 + - @internal/plugin-catalog-customized@0.0.7-next.2 + +## example-backend@0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-backend@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-search-backend@1.2.3-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-events-backend@0.2.3-next.2 + - @backstage/plugin-kafka-backend@0.2.35-next.2 + - @backstage/plugin-proxy-backend@0.2.36-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-backend@0.17.5-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/plugin-playlist-backend@0.2.5-next.2 + - @backstage/plugin-rollbar-backend@0.1.39-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + - @backstage/plugin-tech-insights-backend@0.5.8-next.2 + - @backstage/plugin-techdocs-backend@1.5.3-next.2 + - example-app@0.2.80-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.2 + - @backstage/plugin-azure-devops-backend@0.3.21-next.2 + - @backstage/plugin-azure-sites-backend@0.1.4-next.2 + - @backstage/plugin-badges-backend@0.1.36-next.2 + - @backstage/plugin-code-coverage-backend@0.2.8-next.2 + - @backstage/plugin-explore-backend@0.0.4-next.2 + - @backstage/plugin-graphql-backend@0.1.32-next.2 + - @backstage/plugin-jenkins-backend@0.1.32-next.2 + - @backstage/plugin-permission-backend@0.5.17-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + - @backstage/plugin-todo-backend@0.1.39-next.2 + +## example-backend-next@0.0.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/backend-defaults@0.1.7-next.2 + +## techdocs-cli-embedded-app@0.2.79-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## @internal/plugin-catalog-customized@0.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## @internal/plugin-todo-list@1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## @internal/plugin-todo-list-backend@1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 diff --git a/microsite-next/yarn.lock b/microsite-next/yarn.lock index 5f27b0f062..e03c6d93c5 100644 --- a/microsite-next/yarn.lock +++ b/microsite-next/yarn.lock @@ -6051,9 +6051,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard @@ -8361,11 +8361,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard diff --git a/microsite/blog/2023-01-31-incremental-entity-provider.md b/microsite/blog/2023-01-31-incremental-entity-provider.md new file mode 100644 index 0000000000..c14c3fc15d --- /dev/null +++ b/microsite/blog/2023-01-31-incremental-entity-provider.md @@ -0,0 +1,43 @@ +--- +title: Scaling Backstage Ingestion with Incremental Entity Providers +author: Paul Cowan & Taras Mankovski +authorURL: https://frontside.com/ +--- + +At the heart of [Backstage](https://backstage.io/) is the [Backstage Software Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview), which is a data store that allows an organization to centralize and visualize its many software services and components. Backstage inspects and transforms an organization's disparate software services and parts into a centralized data store. + +![catalog pipeline](assets/2023-01-31/catalog-pipeline.png) + +A common use case is for an organization to want to surface ownership and metadata about repositories. Backstage provides a mechanism for discovering and transforming repository information into a standard data structure and persisting it into the Backstage [Catalog](https://backstage.io/docs/features/software-catalog/software-catalog-overview). This process is known as ingestion, where all data is transformed into a standard Backstage data structure known as an entity. Entities in the Catalog’s data store are accessible to the Backstage App via the REST API. + +Data is transformed into entities via what is known as the ingestion and processing loop, which can be thought of as an [extract, transform and load (ETL) pipeline](https://en.wikipedia.org/wiki/Extract,_transform,_load), where raw data such as GitHub repositories are loaded from GitHub, transformed into entities and outputted to the Catalog. + +## Entity Providers + +Backstage offers what are known as [entity providers](https://backstage.io/docs/features/software-catalog/life-of-an-entity) as a means for ingesting the raw data into the pipeline and transforming them into Backstage entities. For example, Backstage comes with a [GitHub Entity Provider](https://backstage.io/docs/reference/plugin-catalog-backend-module-github) that finds all catalog-info.yaml files in GitHub repositories. The processing loop transforms them into Backstage entities and subsequently persists them to the software catalog. + +Entity providers are a relatively new abstraction and the recommended way to ingest data into the catalog. The Backstage catalog engine starts each registered entity provider, which connects to its data source (e.g., the GitHub Entity Provider connects to GitHub). The entity provider will query the external data source and convert the data into the entity format. Finally, the entity provider issues what is known as a mutation to the catalog engine. A mutation is a signal from the entity provider to the catalog engine that entities are available to be processed and stored. + +A mutation can be either a full mutation or a delta mutation. A full mutation replaces all entities previously ingested by the entity provider with a new set of entities. The entity provider will remove all entities not found in the latest ingestion. A full mutation can be used to ingest relatively small datasets (less than 10,000 entities); however, ingesting more during a full ingestion may cause out-of-memory errors and delay the processing of entities from other entity providers. A delta mutation can surgically add and remove entities from the catalog. A delta mutation is useful when the data source provides events-based APIs like webhooks, which allows the Backstage catalog engine to ingest a small number of entities as they get added, updated and/or deleted. + +## Incremental entity providers + +A large organization typically deals with massive datasets. Until recently, ingesting large datasets with entity providers has been problematic because performing a full ingestion resulted in out-of-memory errors, and many data sources don’t provide webhooks or other events-based APIs. At the same time, the datasets were too large to efficiently manage through targeted delta mutations. + +This is a problem that [DevEx team at HP](http://hp.com) faced when building their software catalog with Backstage. [Damon Kaswell](https://github.com/dekoding), Senior Application Developer on the DevEx team at HP, shared their experience at [BackstageCon 2022](https://www.youtube.com/watch?v=5qHyZntKXRU&list=PLj6h78yzYM2OKySsTuiip3BqmdYZQRnSf&index=13), detailing the problem and the solution that [Frontside](https://frontside.com/) created in collaboration with developers on HP’s DevEx team. + +![Damon Kaswell](assets/2023-01-31/damon.jpg) + +The solution HP and [Frontside](https://frontside.com/) arrived at was to implement an incremental entity provider. An incremental entity provider effectively performs a full mutation using a series of delta mutations combined with a mark and sweep mechanism. It paginates through the dataset, tracking entities retrieved from each page and the cursor of the next page, pausing ingestion every few seconds to give the processing loop time to process existing entities. Once it reaches the end of the dataset, it determines which entities were not ingested during this ingestion cycle and emits a delta mutation to delete unmarked entities. + +Simply by adding a few new tables to the database schema, the incremental ingestion entity provider converts any existing entity provider into an incremental entity provider. These tables allow the incremental entity provider to be long-lived and keep track of its current location in the dataset by persisting a cursor that it uses to page through any large dataset. The larger the dataset, the more pages of data or bursts of work the incremental entity provider will ingest—but there will be no out-of-memory errors, effectively removing scalability problems. + +The results speak for themselves. Migrating from regular entity providers to incremental entity providers reduced ingestion time by 92% – from over 4 and a half hours to just 20 minutes. Incremental entity providers eliminated the ingestion maintenance burden from being a constant problem to a non-issue. Writing reliable integration with external services can now be done in days instead of weeks. + +## Go forth and ingest! + +Backstage provides a robust framework for ingesting data from external sources, but HP needed to scale it beyond its design. The Backstage framework allowed [Frontside](https://frontside.com/) and HP’s developers to extend it with a plugin to support HP’s scaling requirements. + +We're delighted to share that as of [this PR](https://github.com/backstage/backstage/pull/14356), the incremental ingestion backend is available for anyone to use with Backstage. The solution was released open source as [@backstage/plugin-catalog-backend-module-incremental-ingestion](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-incremental-ingestion#backstageplugin-catalog-backend-module-incremental-ingestion) and contains a package for creating incremental entity providers. The plugin's [repository README](https://github.com/backstage/backstage/tree/master/plugins/catalog-backend-module-incremental-ingestion) has detailed configuration and usage outlined. + +The incremental ingestion entity provider is an excellent addition to the Backstage stack. Battle-tested on large datasets, the incremental entity provider is a significant step forward in smoothing the path to successful ingestion at scale. diff --git a/microsite/blog/2023-02-06-whats-ahead-in-2023.md b/microsite/blog/2023-02-06-whats-ahead-in-2023.md new file mode 100644 index 0000000000..a9f06d9ea0 --- /dev/null +++ b/microsite/blog/2023-02-06-whats-ahead-in-2023.md @@ -0,0 +1,58 @@ +--- +title: What’s Ahead in 2023? +author: Lee Mills +authorURL: https://github.com/leemills83 +--- + +# What’s Ahead in 2023? + +![Fewer “vibes” and more climbs (up the contribution ladder)](assets/2023-02-06/whats-ahead.png) + +Okay, everyone. Time to move on from all the 2022 reflections, Top 10 lists, and Wrapped(s), and turn our gaze in the other direction — towards 2023. As the Backstage team moves into the new year, we find ourselves asking those perennial questions: How can we continue to grow and enhance the Backstage community? How can we improve the experience for those adopting Backstage? How can we give the best support to Backstage contributors? + +Well, we don’t have all the answers, but we do have some. So we wanted to share more on three ongoing initiatives aimed at moving the needle forward for these three distinct, yet interrelated, questions. + +- Grow your influence by climbing the contribution ladder +- Come join our SIGs (and push for new ones) +- Work with us to drive a better experience for Backstage adopters + +# Climb the contribution ladder + +Truth be told, we’ve been wanting to grow the maintainer team for some time, and have had multiple requests from contributors and contributing organizations wanting to become maintainers. But, so far, we just haven’t managed to get anything off the ground. What we see is that becoming a maintainer is too hard and the current ownership model doesn’t work. In short, we need to update Backstage governance. + +To address this, we are proposing (RFC links below) the following three initiatives: + +- Introduce more steps in between first-time contributor and maintainer in the form of a contributor ladder (loosely based on the [CNCF Project Template](https://github.com/cncf/project-template/blob/main/CONTRIBUTOR_LADDER.md)). The ladder might look as follows: Contributor, Org Member, Reviewer, Maintainer, Project Maintainer. +- Change the ownership model, for example, divide the project up into several project areas, each covering particular parts of the project. +- Introduce a new process for large contributions in the form of Backstage Enhancement Proposals (BEPs). + +Read more and join the already rich discussion in [RFC: Updated Backstage Governance](https://github.com/backstage/backstage/issues/15317) and [RFC: Backstage Enhancement Proposals](https://github.com/backstage/backstage/issues/15318). The RFC will be open until 13/02/2023. + +# Come join our SIGs (and push for new ones) + +As many of you know, SIG stands for Special Interest Group. The purpose of a SIG is to bring together maintainers and interested contributors within a certain specialist area to discuss, debate, spread knowledge, brainstorm - and drive the overall project forward. They’re also a lot of fun! + +We currently have two SIGs up and running: + +- [Catalog](https://github.com/backstage/community/tree/main/sigs/sig-catalog?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9fx-nTmQga2j12NqzZaL-lYPq-xQjDoXcWKe_JUoa2RGlK65R9j0CIygfYILr0tGEQSvRVN9xzhiJ6LmVxBthKnStfSA&utm_content=241130993&utm_source=hs_email) started up last June and covers all aspects of the systems and components related to the Software Catalog. The group runs every second Tuesday between 16:00 and 17:00 CET. Just show up or hop into [#catalog](https://discord.com/channels/687207715902193673/923144214580191282) (Discord), if you want to talk to us first. Here are the [notes from our sessions so far](https://docs.google.com/document/d/1xg57CDfX2R5jTGbbWANzifm2szEb664kuTwfEEvKgZU/edit#heading=h.iw0hjv6xfb9e). +- [Adoption](https://github.com/backstage/community/tree/main/sigs/sig-adoption?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9CAxtT8JSeJZPh41o3ZnDBi0VBFpbL6fEqXInr9HHOFhU3JAo8HekKg1JzE5rhGP5zOaHcsYDd1YxJWNHw-eSk5mLWkA&utm_content=241130993&utm_source=hs_email) kicked off in December and covers all aspects of the Backstage adoption journey including documentation and tutorials. In the first two meetups, we discussed adoption challenges based on user persona, collecting data about those challenges, and bootstrapping the Catalog to improve metadata quality for adopters. This one runs every second Thursday between 16:00 and 17:00 CET. Again just show up or, if you want to talk to us first, you can do so in [#adoption](https://discord.com/channels/687207715902193673/1045031039061479536) (Discord). Here are the [notes from our sessions](https://docs.google.com/document/d/1zeYSzXYgh897bxPQmwy2btOwCFlEjlUDLf00riySLRc/edit?_hsmi=241130993&_hsenc=p2ANqtz-_nPuE5hW4fnbhJ5-uK8r5HisSTU7rkslKirvqu0g-vdynbitPVYF2AVLAatos2dLoxb2Bgx_g4LBgH02kXoq7_Acd43Q#heading=h.iw0hjv6xfb9e) so far. + +So that’s SIGs. Get involved and join the ones we have up and running. And/or feel free to propose new ones. + +# Help drive a better experience for all adopters + +Throughout all stages of adopting Backstage in an organization — initial discovery, evaluation and POC, and scaling to the wider org — we have identified opportunities where we want to make the journey for Backstage adopters faster and smoother. + +We’ll go step-by-step, but initial plans are to: + +- Make it easier to install, customize, and maintain Backstage +- Provide Golden Paths for adoption +- Improve the experience and the content on [backstage.io](https://backstage.io/docs/overview/what-is-backstage) + +As we move forward, we’d love you to be part of it. Here are some ways that you can contribute to this initiative: + +- Simply give us feedback. [Tell us about your adoption journey](https://spotify.co1.qualtrics.com/jfe/form/SV_cuxhYPB6oQDu7gW). +- Contribute to the pages and documentation on [backstage.io](https://backstage.io/docs/overview/what-is-backstage) +- Pay it forward by making code contributions even during your adoption journey (if you are on one) +- Join the [Adoption](https://github.com/backstage/community/tree/main/sigs/sig-adoption?utm_campaign=Newsletters%20Sent&utm_medium=email&_hsmi=241130993&_hsenc=p2ANqtz-9CAxtT8JSeJZPh41o3ZnDBi0VBFpbL6fEqXInr9HHOFhU3JAo8HekKg1JzE5rhGP5zOaHcsYDd1YxJWNHw-eSk5mLWkA&utm_content=241130993&utm_source=hs_email) SIG +- Chat with us on [#adoption](https://discord.com/channels/687207715902193673/1045031039061479536) (Discord) diff --git a/microsite/blog/assets/2023-01-31/catalog-pipeline.png b/microsite/blog/assets/2023-01-31/catalog-pipeline.png new file mode 100644 index 0000000000..e21de99a7a Binary files /dev/null and b/microsite/blog/assets/2023-01-31/catalog-pipeline.png differ diff --git a/microsite/blog/assets/2023-01-31/damon.jpg b/microsite/blog/assets/2023-01-31/damon.jpg new file mode 100644 index 0000000000..f1e37d354a Binary files /dev/null and b/microsite/blog/assets/2023-01-31/damon.jpg differ diff --git a/microsite/blog/assets/2023-02-06/whats-ahead.png b/microsite/blog/assets/2023-02-06/whats-ahead.png new file mode 100644 index 0000000000..e49f68149d Binary files /dev/null and b/microsite/blog/assets/2023-02-06/whats-ahead.png differ diff --git a/microsite/data/plugins/graphql-voyager.yaml b/microsite/data/plugins/graphql-voyager.yaml new file mode 100644 index 0000000000..c6ebf5e412 --- /dev/null +++ b/microsite/data/plugins/graphql-voyager.yaml @@ -0,0 +1,13 @@ +--- +title: GraphQL Voyager +author: PostNL +authorUrl: https://github.com/postnl +category: Debugging +description: Integrates the GraphQL Voyager tool inside Backstage as a plugin. +documentation: https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager +iconUrl: https://res.cloudinary.com/apideck/image/upload/v1612724234/icons/graphql-voyager.png +npmPackageName: '@backstage/plugin-graphql-voyager' +tags: + - graphql + - graphql-voyager +addedDate: '2023-01-27' diff --git a/microsite/data/plugins/vault.yaml b/microsite/data/plugins/vault.yaml index 822f5dcc90..bb8f799ba7 100644 --- a/microsite/data/plugins/vault.yaml +++ b/microsite/data/plugins/vault.yaml @@ -3,7 +3,7 @@ title: Vault author: Spread Group authorUrl: https://github.com/ivangonzalezacuna category: Vault -description: Visualize a list secrets stored in your vault instance. +description: Visualize a list of the secrets stored in your HashiCorp Vault instance. documentation: https://github.com/backstage/backstage/tree/master/plugins/vault iconUrl: img/vault.png npmPackageName: '@backstage/plugin-vault' diff --git a/microsite/sidebars.json b/microsite/sidebars.json index fcded5ebfb..6baeb20e8b 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -87,7 +87,8 @@ "features/kubernetes/installation", "features/kubernetes/configuration", "features/kubernetes/authentication", - "features/kubernetes/troubleshooting" + "features/kubernetes/troubleshooting", + "features/kubernetes/proxy" ] }, { @@ -365,44 +366,40 @@ ], "FAQ": ["FAQ"], "Experimental Backend System": [ + "backend-system/index", { - "_hidden_": [ - "backend-system/index", - { - "type": "subcategory", - "label": "Architecture", - "ids": [ - "backend-system/architecture/index", - "backend-system/architecture/services", - "backend-system/architecture/plugins", - "backend-system/architecture/extension-points", - "backend-system/architecture/modules", - "backend-system/architecture/naming-patterns" - ] - }, - { - "type": "subcategory", - "label": "Building Backends", - "ids": [ - "backend-system/building-backends/index", - "backend-system/building-backends/migrating" - ] - }, - { - "type": "subcategory", - "label": "Building Plugins & Modules", - "ids": [ - "backend-system/building-plugins-and-modules/index", - "backend-system/building-plugins-and-modules/testing", - "backend-system/building-plugins-and-modules/migrating" - ] - }, - { - "type": "subcategory", - "label": "Core Services", - "ids": ["backend-system/core-services/index"] - } + "type": "subcategory", + "label": "Architecture", + "ids": [ + "backend-system/architecture/index", + "backend-system/architecture/services", + "backend-system/architecture/plugins", + "backend-system/architecture/extension-points", + "backend-system/architecture/modules", + "backend-system/architecture/naming-patterns" ] + }, + { + "type": "subcategory", + "label": "Building Backends", + "ids": [ + "backend-system/building-backends/index", + "backend-system/building-backends/migrating" + ] + }, + { + "type": "subcategory", + "label": "Building Plugins & Modules", + "ids": [ + "backend-system/building-plugins-and-modules/index", + "backend-system/building-plugins-and-modules/testing", + "backend-system/building-plugins-and-modules/migrating" + ] + }, + { + "type": "subcategory", + "label": "Core Services", + "ids": ["backend-system/core-services/index"] } ] } diff --git a/microsite/siteConfig.js b/microsite/siteConfig.js index 68226b5681..5329ebb688 100644 --- a/microsite/siteConfig.js +++ b/microsite/siteConfig.js @@ -138,8 +138,9 @@ const siteConfig = { ], algolia: { - apiKey: '8d115c9875ba0f4feaee95bab55a1645', - indexName: 'backstage', + apiKey: '10b9e6c92a4513c1cf390f50e53aad1f', + indexName: 'backstage_io', + appId: 'JCMFNHCHI8', searchParameters: {}, // Optional (if provided by Algolia) }, }; diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 3bc81619e3..95b0c2885b 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -7369,11 +7369,11 @@ __metadata: linkType: hard "prettier@npm:^2.6.2": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard diff --git a/package.json b/package.json index d458fadb9d..286e750f29 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "create-plugin": "echo \"use 'yarn new' instead\"", "release": "node scripts/prepare-release.js && changeset version && yarn prettier --write '{packages,plugins}/*/{package.json,CHANGELOG.md}' '.changeset/*.json' && yarn install --no-immutable", "prettier:check": "prettier --check .", + "prettier:fix": "prettier --write .", "storybook": "yarn ./storybook run start", "snyk:test": "npx snyk test --yarn-workspaces --strict-out-of-sync=false", "snyk:test:package": "yarn snyk:test --include", @@ -46,7 +47,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.11.0-next.0", + "version": "1.11.0-next.2", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 9a492ecaf7..e785ffe05a 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/app-defaults +## 1.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + +## 1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-permission-react@0.4.9 + ## 1.1.0 ### Minor Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index edfad83e78..8ffdfd60bc 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.1.0", + "version": "1.1.1-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 308dca26c5..818d21840d 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,133 @@ # example-app +## 0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/plugin-scaffolder@1.11.0-next.2 + - @backstage/cli@0.22.2-next.1 + - @backstage/plugin-api-docs@0.9.0-next.2 + - @backstage/plugin-tech-radar@0.6.1-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-explore@0.4.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/plugin-sentry@0.5.0-next.2 + - @backstage/plugin-circleci@0.3.15-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.2 + - @backstage/plugin-search@1.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.0-next.2 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-airbrake@0.3.15-next.2 + - @backstage/plugin-apache-airflow@0.2.8-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.2 + - @backstage/plugin-badges@0.2.39-next.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-graph@0.2.27-next.2 + - @backstage/plugin-catalog-import@0.9.5-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cloudbuild@0.3.15-next.2 + - @backstage/plugin-code-coverage@0.2.8-next.2 + - @backstage/plugin-cost-insights@0.12.4-next.2 + - @backstage/plugin-dynatrace@2.0.0-next.2 + - @backstage/plugin-gcalendar@0.3.11-next.1 + - @backstage/plugin-gcp-projects@0.3.34-next.1 + - @backstage/plugin-github-actions@0.5.15-next.2 + - @backstage/plugin-gocd@0.1.21-next.2 + - @backstage/plugin-graphiql@0.2.47-next.1 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-jenkins@0.7.14-next.2 + - @backstage/plugin-kafka@0.3.15-next.2 + - @backstage/plugin-kubernetes@0.7.8-next.2 + - @backstage/plugin-newrelic@0.3.33-next.1 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.2 + - @backstage/plugin-org@0.6.5-next.2 + - @backstage/plugin-pagerduty@0.5.8-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist@0.1.6-next.2 + - @backstage/plugin-rollbar@0.4.15-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.1 + - @backstage/plugin-stack-overflow@0.1.11-next.2 + - @backstage/plugin-tech-insights@0.3.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.2 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + - @backstage/plugin-todo@0.2.17-next.2 + - @backstage/plugin-user-settings@0.6.3-next.2 + - @internal/plugin-catalog-customized@0.0.7-next.2 + +## 0.2.80-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.1 + - @backstage/plugin-scaffolder@1.11.0-next.1 + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-tech-insights@0.3.7-next.1 + - @backstage/plugin-search@1.1.0-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.10-next.1 + - @backstage/plugin-dynatrace@2.0.0-next.1 + - @backstage/plugin-playlist@0.1.6-next.1 + - @backstage/plugin-home@0.4.31-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/plugin-kubernetes@0.7.8-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-tech-radar@0.6.1-next.0 + - @backstage/plugin-explore@0.4.0-next.1 + - @backstage/plugin-apache-airflow@0.2.8-next.0 + - @backstage/plugin-circleci@0.3.15-next.1 + - @backstage/plugin-sentry@0.4.8-next.1 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-airbrake@0.3.15-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/app-defaults@1.1.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-api-docs@0.8.15-next.1 + - @backstage/plugin-azure-devops@0.2.6-next.1 + - @backstage/plugin-azure-sites@0.1.4-next.1 + - @backstage/plugin-badges@0.2.39-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-graph@0.2.27-next.1 + - @backstage/plugin-catalog-import@0.9.5-next.1 + - @backstage/plugin-cloudbuild@0.3.15-next.1 + - @backstage/plugin-code-coverage@0.2.8-next.1 + - @backstage/plugin-cost-insights@0.12.4-next.1 + - @backstage/plugin-gcalendar@0.3.11-next.0 + - @backstage/plugin-gcp-projects@0.3.34-next.0 + - @backstage/plugin-github-actions@0.5.15-next.1 + - @backstage/plugin-gocd@0.1.21-next.1 + - @backstage/plugin-graphiql@0.2.47-next.0 + - @backstage/plugin-jenkins@0.7.14-next.1 + - @backstage/plugin-kafka@0.3.15-next.1 + - @backstage/plugin-lighthouse@0.3.15-next.1 + - @backstage/plugin-newrelic@0.3.33-next.0 + - @backstage/plugin-newrelic-dashboard@0.2.8-next.1 + - @backstage/plugin-org@0.6.5-next.1 + - @backstage/plugin-pagerduty@0.5.8-next.1 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-rollbar@0.4.15-next.1 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-shortcuts@0.3.7-next.0 + - @backstage/plugin-stack-overflow@0.1.11-next.1 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + - @backstage/plugin-todo@0.2.17-next.1 + - @backstage/plugin-user-settings@0.6.3-next.1 + - @internal/plugin-catalog-customized@0.0.7-next.1 + ## 0.2.80-next.0 ### Patch Changes diff --git a/packages/app/cypress/.eslintrc.json b/packages/app/cypress/.eslintrc.json index 2b3a458b95..a467608916 100644 --- a/packages/app/cypress/.eslintrc.json +++ b/packages/app/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/app/package.json b/packages/app/package.json index f1edc7ee0e..80ee11ea15 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.80-next.0", + "version": "0.2.80-next.2", "private": true, "backstage": { "role": "frontend" @@ -41,6 +41,7 @@ "@backstage/plugin-kafka": "workspace:^", "@backstage/plugin-kubernetes": "workspace:^", "@backstage/plugin-lighthouse": "workspace:^", + "@backstage/plugin-microsoft-calendar": "workspace:^", "@backstage/plugin-newrelic": "workspace:^", "@backstage/plugin-newrelic-dashboard": "workspace:^", "@backstage/plugin-org": "workspace:^", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 8984a69259..f789328104 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -78,6 +78,7 @@ import { ExpandableNavigation, ReportIssue, TextSize, + LightBox, } from '@backstage/plugin-techdocs-module-addons-contrib'; import { SettingsLayout, @@ -203,6 +204,7 @@ const routes = ( + + ); diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index e432e1a00e..29023738af 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -27,6 +27,7 @@ import { import { Content, Header, Page } from '@backstage/core-components'; import { HomePageSearchBar } from '@backstage/plugin-search'; import { HomePageCalendar } from '@backstage/plugin-gcalendar'; +import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; import Grid from '@material-ui/core/Grid'; import React from 'react'; @@ -114,6 +115,9 @@ export const homePage = ( + + + diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index c521bcf86c..8a2e7fba53 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -68,7 +68,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( const MockDelayComponent = ( props: NextFieldExtensionComponentProps<{ test?: string }>, ) => { - const { onChange, formData, rawErrors } = props; + const { onChange, formData, rawErrors = [] } = props; return ( void }) => { const classes = useStyles(); const navigate = useNavigate(); - const { transitions } = useTheme(); - const { focusContent } = useContent(); - const catalogApi = useApi(catalogApiRef); const { term, types } = useSearch(); @@ -91,19 +82,14 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { searchBarRef?.current?.focus(); }); - const handleSearchResultClick = useCallback(() => { - toggleModal(); - setTimeout(focusContent, transitions.duration.leavingScreen); - }, [toggleModal, focusContent, transitions]); - const handleSearchBarKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === 'Enter') { - handleSearchResultClick(); + toggleModal(); navigate(searchPagePath); } }, - [navigate, searchPagePath, handleSearchResultClick], + [navigate, searchPagePath, toggleModal], ); return ( @@ -187,7 +173,7 @@ export const SearchModal = ({ toggleModal }: { toggleModal: () => void }) => { alignItems="center" > - + void }) => { - + } /> } /> } /> diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index 8167889b02..6c4f06aed9 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -79,6 +79,7 @@ const SearchPage = () => { import { BackendFeature } from '@backstage/backend-plugin-api'; +import { CacheClient } from '@backstage/backend-common'; import { Config } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import { CorsOptions } from 'cors'; import { ErrorRequestHandler } from 'express'; import { Express as Express_2 } from 'express'; -import { ExtensionPoint } from '@backstage/backend-plugin-api'; import { Format } from 'logform'; import { Handler } from 'express'; import { HelmetOptions } from 'helmet'; import * as http from 'http'; import { HttpRouterService } from '@backstage/backend-plugin-api'; import { IdentityService } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { LoggerService } from '@backstage/backend-plugin-api'; -import { LogMeta } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { PluginCacheManager } from '@backstage/backend-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RequestHandler } from 'express'; @@ -34,7 +33,6 @@ import { RootLoggerService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceFactoryOrFunction } from '@backstage/backend-plugin-api'; -import { ServiceRef } from '@backstage/backend-plugin-api'; import { TokenManagerService } from '@backstage/backend-plugin-api'; import { transport } from 'winston'; import { UrlReader } from '@backstage/backend-common'; @@ -50,10 +48,7 @@ export interface Backend { } // @public (undocumented) -export const cacheFactory: () => ServiceFactory; - -// @public (undocumented) -export const configFactory: () => ServiceFactory; +export const cacheServiceFactory: () => ServiceFactory; // @public (undocumented) export interface ConfigFactoryOptions { @@ -61,6 +56,11 @@ export interface ConfigFactoryOptions { remote?: LoadConfigOptionsRemote; } +// @public (undocumented) +export const configServiceFactory: ( + options?: ConfigFactoryOptions | undefined, +) => ServiceFactory; + // @public (undocumented) export function createConfigSecretEnumerator(options: { logger: LoggerService; @@ -88,7 +88,10 @@ export interface CreateSpecializedBackendOptions { } // @public (undocumented) -export const databaseFactory: () => ServiceFactory; +export const databaseServiceFactory: () => ServiceFactory< + PluginDatabaseManager, + 'plugin' +>; // @public export class DefaultRootHttpRouter implements RootHttpRouterService { @@ -106,7 +109,10 @@ export interface DefaultRootHttpRouterOptions { } // @public (undocumented) -export const discoveryFactory: () => ServiceFactory; +export const discoveryServiceFactory: () => ServiceFactory< + PluginEndpointDiscovery, + 'plugin' +>; // @public export interface ExtendedHttpServer extends http.Server { @@ -118,20 +124,20 @@ export interface ExtendedHttpServer extends http.Server { stop(): Promise; } -// @public (undocumented) -export const httpRouterFactory: ( - options?: HttpRouterFactoryOptions | undefined, -) => ServiceFactory; - // @public (undocumented) export interface HttpRouterFactoryOptions { getPath?(pluginId: string): string; } +// @public (undocumented) +export const httpRouterServiceFactory: ( + options?: HttpRouterFactoryOptions | undefined, +) => ServiceFactory; + // @public export type HttpServerCertificateOptions = | { - type: 'plain'; + type: 'pem'; key: string; cert: string; } @@ -151,19 +157,22 @@ export type HttpServerOptions = { }; }; -// @public (undocumented) -export const identityFactory: ( - options?: IdentityFactoryOptions | undefined, -) => ServiceFactory; - // @public export type IdentityFactoryOptions = { issuer?: string; algorithms?: string[]; }; +// @public (undocumented) +export const identityServiceFactory: ( + options?: IdentityFactoryOptions | undefined, +) => ServiceFactory; + // @public -export const lifecycleFactory: () => ServiceFactory; +export const lifecycleServiceFactory: () => ServiceFactory< + LifecycleService, + 'plugin' +>; // @public export function loadBackendConfig(options: { @@ -174,7 +183,10 @@ export function loadBackendConfig(options: { }>; // @public (undocumented) -export const loggerFactory: () => ServiceFactory; +export const loggerServiceFactory: () => ServiceFactory< + LoggerService, + 'plugin' +>; // @public export class MiddlewareFactory { @@ -202,7 +214,10 @@ export interface MiddlewareFactoryOptions { } // @public (undocumented) -export const permissionsFactory: () => ServiceFactory; +export const permissionsServiceFactory: () => ServiceFactory< + PermissionsService, + 'plugin' +>; // @public export function readCorsOptions(config?: Config): CorsOptions; @@ -214,7 +229,7 @@ export function readHelmetOptions(config?: Config): HelmetOptions; export function readHttpServerOptions(config?: Config): HttpServerOptions; // @public (undocumented) -export interface RootHttpRouterConfigureOptions { +export interface RootHttpRouterConfigureContext { // (undocumented) app: Express_2; // (undocumented) @@ -229,55 +244,64 @@ export interface RootHttpRouterConfigureOptions { routes: RequestHandler; } -// @public (undocumented) -export const rootHttpRouterFactory: () => ServiceFactory; - // @public (undocumented) export type RootHttpRouterFactoryOptions = { indexPath?: string | false; - configure?(options: RootHttpRouterConfigureOptions): void; + configure?(context: RootHttpRouterConfigureContext): void; }; +// @public (undocumented) +export const rootHttpRouterServiceFactory: ( + options?: RootHttpRouterFactoryOptions | undefined, +) => ServiceFactory; + // @public -export const rootLifecycleFactory: () => ServiceFactory; +export const rootLifecycleServiceFactory: () => ServiceFactory< + RootLifecycleService, + 'root' +>; // @public (undocumented) -export const rootLoggerFactory: () => ServiceFactory; +export const rootLoggerServiceFactory: () => ServiceFactory< + RootLoggerService, + 'root' +>; // @public (undocumented) -export const schedulerFactory: () => ServiceFactory; +export const schedulerServiceFactory: () => ServiceFactory< + SchedulerService, + 'plugin' +>; // @public (undocumented) -export type ServiceOrExtensionPoint = - | ExtensionPoint - | ServiceRef; +export const tokenManagerServiceFactory: () => ServiceFactory< + TokenManagerService, + 'plugin' +>; // @public (undocumented) -export const tokenManagerFactory: () => ServiceFactory; - -// @public (undocumented) -export const urlReaderFactory: () => ServiceFactory; +export const urlReaderServiceFactory: () => ServiceFactory; // @public export class WinstonLogger implements RootLoggerService { // (undocumented) addRedactions(redactions: Iterable): void; // (undocumented) - child(meta: LogMeta): LoggerService; + child(meta: JsonObject): LoggerService; static colorFormat(): Format; static create(options: WinstonLoggerOptions): WinstonLogger; // (undocumented) - debug(message: string, meta?: LogMeta): void; + debug(message: string, meta?: JsonObject): void; // (undocumented) - error(message: string, meta?: LogMeta): void; + error(message: string, meta?: JsonObject): void; // (undocumented) - info(message: string, meta?: LogMeta): void; + info(message: string, meta?: JsonObject): void; static redacter(): { format: Format; add: (redactions: Iterable) => void; }; // (undocumented) - warn(message: string, meta?: LogMeta): void; + warn(message: string, meta?: JsonObject): void; } // @public (undocumented) @@ -287,7 +311,7 @@ export interface WinstonLoggerOptions { // (undocumented) level: string; // (undocumented) - meta?: LogMeta; + meta?: JsonObject; // (undocumented) transports: transport[]; } diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index ef34fbdb25..3bbae1f7fe 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.3.2-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-app-api/src/http/config.test.ts b/packages/backend-app-api/src/http/config.test.ts index f54ba927ca..577bae08f3 100644 --- a/packages/backend-app-api/src/http/config.test.ts +++ b/packages/backend-app-api/src/http/config.test.ts @@ -53,7 +53,7 @@ describe('readHttpServerOptions', () => { { listen: { host: '', port: 7007 }, https: { - certificate: { type: 'plain', cert: 'my-cert', key: 'my-key' }, + certificate: { type: 'pem', cert: 'my-cert', key: 'my-key' }, }, }, ], diff --git a/packages/backend-app-api/src/http/config.ts b/packages/backend-app-api/src/http/config.ts index e3b41c63de..ec29a8a044 100644 --- a/packages/backend-app-api/src/http/config.ts +++ b/packages/backend-app-api/src/http/config.ts @@ -93,7 +93,7 @@ function readHttpsOptions(config?: Config): HttpServerOptions['https'] { return { certificate: { - type: 'plain', + type: 'pem', cert: cc.getString('certificate.cert'), key: cc.getString('certificate.key'), }, diff --git a/packages/backend-app-api/src/http/types.ts b/packages/backend-app-api/src/http/types.ts index ff96f69bff..2298ef11ff 100644 --- a/packages/backend-app-api/src/http/types.ts +++ b/packages/backend-app-api/src/http/types.ts @@ -51,7 +51,7 @@ export type HttpServerOptions = { */ export type HttpServerCertificateOptions = | { - type: 'plain'; + type: 'pem'; key: string; cert: string; } diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index d32b816523..06a189508b 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -16,9 +16,9 @@ import { LoggerService, - LogMeta, RootLoggerService, } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { Format, TransformableInfo } from 'logform'; import { Logger, @@ -33,7 +33,7 @@ import { escapeRegExp } from '../lib/escapeRegExp'; * @public */ export interface WinstonLoggerOptions { - meta?: LogMeta; + meta?: JsonObject; level: string; format: Format; transports: Transport[]; @@ -150,23 +150,23 @@ export class WinstonLogger implements RootLoggerService { this.#addRedactions = addRedactions; } - error(message: string, meta?: LogMeta): void { + error(message: string, meta?: JsonObject): void { this.#winston.error(message, meta); } - warn(message: string, meta?: LogMeta): void { + warn(message: string, meta?: JsonObject): void { this.#winston.warn(message, meta); } - info(message: string, meta?: LogMeta): void { + info(message: string, meta?: JsonObject): void { this.#winston.info(message, meta); } - debug(message: string, meta?: LogMeta): void { + debug(message: string, meta?: JsonObject): void { this.#winston.debug(message, meta); } - child(meta: LogMeta): LoggerService { + child(meta: JsonObject): LoggerService { return new WinstonLogger(this.#winston.child(meta)); } diff --git a/packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts similarity index 89% rename from packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts rename to packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts index 426a890c00..2208249280 100644 --- a/packages/backend-app-api/src/services/implementations/cache/cacheFactory.ts +++ b/packages/backend-app-api/src/services/implementations/cache/cacheServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const cacheFactory = createServiceFactory({ +export const cacheServiceFactory = createServiceFactory({ service: coreServices.cache, deps: { config: coreServices.config, @@ -31,6 +31,6 @@ export const cacheFactory = createServiceFactory({ return CacheManager.fromConfig(config); }, async factory({ plugin }, manager) { - return manager.forPlugin(plugin.getId()); + return manager.forPlugin(plugin.getId()).getClient(); }, }); diff --git a/packages/backend-app-api/src/services/implementations/cache/index.ts b/packages/backend-app-api/src/services/implementations/cache/index.ts index 3d1bcd75a7..f96ee77182 100644 --- a/packages/backend-app-api/src/services/implementations/cache/index.ts +++ b/packages/backend-app-api/src/services/implementations/cache/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { cacheFactory } from './cacheFactory'; +export { cacheServiceFactory } from './cacheServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/config/configFactory.ts b/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts similarity index 76% rename from packages/backend-app-api/src/services/implementations/config/configFactory.ts rename to packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts index 0ec15c29fe..459c0d9f0c 100644 --- a/packages/backend-app-api/src/services/implementations/config/configFactory.ts +++ b/packages/backend-app-api/src/services/implementations/config/configServiceFactory.ts @@ -35,13 +35,14 @@ export interface ConfigFactoryOptions { } /** @public */ -export const configFactory = createServiceFactory({ - service: coreServices.config, - deps: {}, - async factory({}, options?: ConfigFactoryOptions) { - const { argv = process.argv, remote } = options ?? {}; - - const { config } = await loadBackendConfig({ argv, remote }); - return config; - }, -}); +export const configServiceFactory = createServiceFactory( + (options?: ConfigFactoryOptions) => ({ + service: coreServices.config, + deps: {}, + async factory({}) { + const { argv = process.argv, remote } = options ?? {}; + const { config } = await loadBackendConfig({ argv, remote }); + return config; + }, + }), +); diff --git a/packages/backend-app-api/src/services/implementations/config/index.ts b/packages/backend-app-api/src/services/implementations/config/index.ts index b23c47ce0a..690f1e2d36 100644 --- a/packages/backend-app-api/src/services/implementations/config/index.ts +++ b/packages/backend-app-api/src/services/implementations/config/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { configFactory } from './configFactory'; -export type { ConfigFactoryOptions } from './configFactory'; +export { configServiceFactory } from './configServiceFactory'; +export type { ConfigFactoryOptions } from './configServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts similarity index 79% rename from packages/backend-app-api/src/services/implementations/database/databaseFactory.ts rename to packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts index 8baf84cb69..05e2f1deb9 100644 --- a/packages/backend-app-api/src/services/implementations/database/databaseFactory.ts +++ b/packages/backend-app-api/src/services/implementations/database/databaseServiceFactory.ts @@ -22,11 +22,12 @@ import { import { ConfigReader } from '@backstage/config'; /** @public */ -export const databaseFactory = createServiceFactory({ +export const databaseServiceFactory = createServiceFactory({ service: coreServices.database, deps: { config: coreServices.config, - plugin: coreServices.pluginMetadata, + lifecycle: coreServices.lifecycle, + pluginMetadata: coreServices.pluginMetadata, }, async createRootContext({ config }) { return config.getOptional('backend.database') @@ -39,7 +40,10 @@ export const databaseFactory = createServiceFactory({ }), ); }, - async factory({ plugin }, databaseManager) { - return databaseManager.forPlugin(plugin.getId()); + async factory({ pluginMetadata, lifecycle }, databaseManager) { + return databaseManager.forPlugin(pluginMetadata.getId(), { + pluginMetadata, + lifecycle, + }); }, }); diff --git a/packages/backend-app-api/src/services/implementations/database/index.ts b/packages/backend-app-api/src/services/implementations/database/index.ts index 0045630e15..d676c8013e 100644 --- a/packages/backend-app-api/src/services/implementations/database/index.ts +++ b/packages/backend-app-api/src/services/implementations/database/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { databaseFactory } from './databaseFactory'; +export { databaseServiceFactory } from './databaseServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts similarity index 93% rename from packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts rename to packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts index 51ea3c881d..6c0da8521d 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/discoveryFactory.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/discoveryServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const discoveryFactory = createServiceFactory({ +export const discoveryServiceFactory = createServiceFactory({ service: coreServices.discovery, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/discovery/index.ts b/packages/backend-app-api/src/services/implementations/discovery/index.ts index 182b9f6cd2..7b3b9816b1 100644 --- a/packages/backend-app-api/src/services/implementations/discovery/index.ts +++ b/packages/backend-app-api/src/services/implementations/discovery/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { discoveryFactory } from './discoveryFactory'; +export { discoveryServiceFactory } from './discoveryServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts similarity index 85% rename from packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts rename to packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts index 150bd628f5..e52b4c9a36 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.test.ts @@ -14,19 +14,12 @@ * limitations under the License. */ -import { - HttpRouterService, - ServiceFactory, -} from '@backstage/backend-plugin-api'; -import { httpRouterFactory } from './httpRouterFactory'; +import { httpRouterServiceFactory } from './httpRouterServiceFactory'; describe('httpRouterFactory', () => { it('should register plugin paths', async () => { const rootHttpRouter = { use: jest.fn() }; - const factory = httpRouterFactory() as Exclude< - ServiceFactory, - { scope: 'root' } - >; + const factory = httpRouterServiceFactory() as any; const handler1 = () => {}; const router1 = await factory.factory( @@ -55,9 +48,9 @@ describe('httpRouterFactory', () => { it('should use custom path generator', async () => { const rootHttpRouter = { use: jest.fn() }; - const factory = httpRouterFactory({ + const factory = httpRouterServiceFactory({ getPath: id => `/some/${id}/path`, - }) as Exclude, { scope: 'root' }>; + }) as any; const handler1 = () => {}; const router1 = await factory.factory( diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts rename to packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts index 218910345d..bbd54b7ade 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/httpRouterServiceFactory.ts @@ -31,7 +31,7 @@ export interface HttpRouterFactoryOptions { } /** @public */ -export const httpRouterFactory = createServiceFactory( +export const httpRouterServiceFactory = createServiceFactory( (options?: HttpRouterFactoryOptions) => ({ service: coreServices.httpRouter, deps: { diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/index.ts b/packages/backend-app-api/src/services/implementations/httpRouter/index.ts index f2db660414..9dfb01c5be 100644 --- a/packages/backend-app-api/src/services/implementations/httpRouter/index.ts +++ b/packages/backend-app-api/src/services/implementations/httpRouter/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { httpRouterFactory } from './httpRouterFactory'; -export type { HttpRouterFactoryOptions } from './httpRouterFactory'; +export { httpRouterServiceFactory } from './httpRouterServiceFactory'; +export type { HttpRouterFactoryOptions } from './httpRouterServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/identity/identityFactory.ts b/packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/identity/identityFactory.ts rename to packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts index 0031979390..58da1c37d5 100644 --- a/packages/backend-app-api/src/services/implementations/identity/identityFactory.ts +++ b/packages/backend-app-api/src/services/implementations/identity/identityServiceFactory.ts @@ -34,7 +34,7 @@ export type IdentityFactoryOptions = { }; /** @public */ -export const identityFactory = createServiceFactory( +export const identityServiceFactory = createServiceFactory( (options?: IdentityFactoryOptions) => ({ service: coreServices.identity, deps: { diff --git a/packages/backend-app-api/src/services/implementations/identity/index.ts b/packages/backend-app-api/src/services/implementations/identity/index.ts index 9382232620..bf2f4436dd 100644 --- a/packages/backend-app-api/src/services/implementations/identity/index.ts +++ b/packages/backend-app-api/src/services/implementations/identity/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { identityFactory } from './identityFactory'; -export type { IdentityFactoryOptions } from './identityFactory'; +export { identityServiceFactory } from './identityServiceFactory'; +export type { IdentityFactoryOptions } from './identityServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/index.ts b/packages/backend-app-api/src/services/implementations/lifecycle/index.ts index cfca37a162..8dac4c26b4 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/index.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { lifecycleFactory } from './lifecycleFactory'; +export { lifecycleServiceFactory } from './lifecycleServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts similarity index 76% rename from packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts rename to packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts index b2f3a9f70b..79658c0d42 100644 --- a/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/lifecycle/lifecycleServiceFactory.ts @@ -17,12 +17,14 @@ import { createServiceFactory, coreServices, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, } from '@backstage/backend-plugin-api'; /** * Allows plugins to register shutdown hooks that are run when the process is about to exit. - * @public */ -export const lifecycleFactory = createServiceFactory({ + * @public + */ +export const lifecycleServiceFactory = createServiceFactory({ service: coreServices.lifecycle, deps: { logger: coreServices.logger, @@ -32,11 +34,12 @@ export const lifecycleFactory = createServiceFactory({ async factory({ rootLifecycle, logger, pluginMetadata }) { const plugin = pluginMetadata.getId(); return { - addShutdownHook(options: LifecycleServiceShutdownHook): void { - rootLifecycle.addShutdownHook({ - ...options, - - logger: options.logger?.child({ plugin }) ?? logger, + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + rootLifecycle.addShutdownHook(hook, { + logger: options?.logger?.child({ plugin }) ?? logger, }); }, }; diff --git a/packages/backend-app-api/src/services/implementations/logger/index.ts b/packages/backend-app-api/src/services/implementations/logger/index.ts index acef1b178f..ca52bf5193 100644 --- a/packages/backend-app-api/src/services/implementations/logger/index.ts +++ b/packages/backend-app-api/src/services/implementations/logger/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { loggerFactory } from './loggerFactory'; +export { loggerServiceFactory } from './loggerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts rename to packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts index 60c91d0ee6..d9158529ca 100644 --- a/packages/backend-app-api/src/services/implementations/logger/loggerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/logger/loggerServiceFactory.ts @@ -20,7 +20,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const loggerFactory = createServiceFactory({ +export const loggerServiceFactory = createServiceFactory({ service: coreServices.logger, deps: { rootLogger: coreServices.rootLogger, diff --git a/packages/backend-app-api/src/services/implementations/permissions/index.ts b/packages/backend-app-api/src/services/implementations/permissions/index.ts index 29a6aa237a..781dda31a0 100644 --- a/packages/backend-app-api/src/services/implementations/permissions/index.ts +++ b/packages/backend-app-api/src/services/implementations/permissions/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { permissionsFactory } from './permissionsFactory'; +export { permissionsServiceFactory } from './permissionsServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts rename to packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts index 4eb05e3e4c..38cba73eda 100644 --- a/packages/backend-app-api/src/services/implementations/permissions/permissionsFactory.ts +++ b/packages/backend-app-api/src/services/implementations/permissions/permissionsServiceFactory.ts @@ -21,7 +21,7 @@ import { import { ServerPermissionClient } from '@backstage/plugin-permission-node'; /** @public */ -export const permissionsFactory = createServiceFactory({ +export const permissionsServiceFactory = createServiceFactory({ service: coreServices.permissions, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts index e24662df05..8437399fec 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/index.ts @@ -15,10 +15,10 @@ */ export { - rootHttpRouterFactory, + rootHttpRouterServiceFactory, type RootHttpRouterFactoryOptions, - type RootHttpRouterConfigureOptions, -} from './rootHttpRouterFactory'; + type RootHttpRouterConfigureContext, +} from './rootHttpRouterServiceFactory'; export { DefaultRootHttpRouter, type DefaultRootHttpRouterOptions, diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts similarity index 55% rename from packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts rename to packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts index 58f8cc2db1..5eaf8aa152 100644 --- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -32,7 +32,7 @@ import { DefaultRootHttpRouter } from './DefaultRootHttpRouter'; /** * @public */ -export interface RootHttpRouterConfigureOptions { +export interface RootHttpRouterConfigureContext { app: Express; middleware: MiddlewareFactory; routes: RequestHandler; @@ -51,14 +51,11 @@ export type RootHttpRouterFactoryOptions = { */ indexPath?: string | false; - configure?(options: RootHttpRouterConfigureOptions): void; + configure?(context: RootHttpRouterConfigureContext): void; }; -function defaultConfigure({ - app, - routes, - middleware, -}: RootHttpRouterConfigureOptions) { +function defaultConfigure(context: RootHttpRouterConfigureContext) { + const { app, routes, middleware } = context; app.use(middleware.helmet()); app.use(middleware.cors()); app.use(middleware.compression()); @@ -69,50 +66,42 @@ function defaultConfigure({ } /** @public */ -export const rootHttpRouterFactory = createServiceFactory({ - service: coreServices.rootHttpRouter, - deps: { - config: coreServices.config, - rootLogger: coreServices.rootLogger, - lifecycle: coreServices.rootLifecycle, - }, - async factory( - { config, rootLogger, lifecycle }, - { - indexPath, - configure = defaultConfigure, - }: RootHttpRouterFactoryOptions = {}, - ) { - const logger = rootLogger.child({ service: 'rootHttpRouter' }); - const app = express(); +export const rootHttpRouterServiceFactory = createServiceFactory( + (options?: RootHttpRouterFactoryOptions) => ({ + service: coreServices.rootHttpRouter, + deps: { + config: coreServices.config, + rootLogger: coreServices.rootLogger, + lifecycle: coreServices.rootLifecycle, + }, + async factory({ config, rootLogger, lifecycle }) { + const { indexPath, configure = defaultConfigure } = options ?? {}; + const logger = rootLogger.child({ service: 'rootHttpRouter' }); + const app = express(); - const router = DefaultRootHttpRouter.create({ indexPath }); - const middleware = MiddlewareFactory.create({ config, logger }); + const router = DefaultRootHttpRouter.create({ indexPath }); + const middleware = MiddlewareFactory.create({ config, logger }); - configure({ - app, - routes: router.handler(), - middleware, - config, - logger, - lifecycle, - }); + configure({ + app, + routes: router.handler(), + middleware, + config, + logger, + lifecycle, + }); - const server = await createHttpServer( - app, - readHttpServerOptions(config.getOptionalConfig('backend')), - { logger }, - ); + const server = await createHttpServer( + app, + readHttpServerOptions(config.getOptionalConfig('backend')), + { logger }, + ); - lifecycle.addShutdownHook({ - async fn() { - await server.stop(); - }, - logger, - }); + lifecycle.addShutdownHook(() => server.stop()); - await server.start(); + await server.start(); - return router; - }, -}); + return router; + }, + }), +); diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts index 8adefbfe84..86589cd23e 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { rootLifecycleFactory } from './rootLifecycleFactory'; +export { rootLifecycleServiceFactory } from './rootLifecycleServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts similarity index 73% rename from packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts rename to packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts index fc1c266775..8d2b2af3d5 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.test.ts @@ -15,17 +15,13 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { BackendLifecycleImpl } from './rootLifecycleFactory'; +import { BackendLifecycleImpl } from './rootLifecycleServiceFactory'; describe('lifecycleService', () => { it('should execute registered shutdown hook', async () => { const service = new BackendLifecycleImpl(getVoidLogger()); const hook = jest.fn(); - service.addShutdownHook({ - fn: async () => { - hook(); - }, - }); + service.addShutdownHook(() => hook()); // should not execute the hook more than once. await service.shutdown(); await service.shutdown(); @@ -35,10 +31,16 @@ describe('lifecycleService', () => { it('should not throw errors', async () => { const service = new BackendLifecycleImpl(getVoidLogger()); - service.addShutdownHook({ - fn: async () => { - throw new Error('oh no'); - }, + service.addShutdownHook(() => { + throw new Error('oh no'); + }); + await expect(service.shutdown()).resolves.toBeUndefined(); + }); + + it('should not throw async errors', async () => { + const service = new BackendLifecycleImpl(getVoidLogger()); + service.addShutdownHook(async () => { + throw new Error('oh no'); }); await expect(service.shutdown()).resolves.toBeUndefined(); }); diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts similarity index 71% rename from packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts rename to packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts index f451c38f20..f379c2ec52 100644 --- a/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLifecycle/rootLifecycleServiceFactory.ts @@ -18,21 +18,25 @@ import { createServiceFactory, coreServices, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, RootLifecycleService, LoggerService, } from '@backstage/backend-plugin-api'; -const CALLBACKS = ['SIGTERM', 'SIGINT', 'beforeExit']; export class BackendLifecycleImpl implements RootLifecycleService { - constructor(private readonly logger: LoggerService) { - CALLBACKS.map(signal => process.on(signal, () => this.shutdown())); - } + constructor(private readonly logger: LoggerService) {} #isCalled = false; - #shutdownTasks: Array = []; + #shutdownTasks: Array<{ + hook: LifecycleServiceShutdownHook; + options?: LifecycleServiceShutdownOptions; + }> = []; - addShutdownHook(options: LifecycleServiceShutdownHook): void { - this.#shutdownTasks.push(options); + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void { + this.#shutdownTasks.push({ hook, options }); } async shutdown(): Promise { @@ -43,10 +47,10 @@ export class BackendLifecycleImpl implements RootLifecycleService { this.logger.info(`Running ${this.#shutdownTasks.length} shutdown tasks...`); await Promise.all( - this.#shutdownTasks.map(async hook => { - const { logger = this.logger } = hook; + this.#shutdownTasks.map(async ({ hook, options }) => { + const logger = options?.logger ?? this.logger; try { - await hook.fn(); + await hook(); logger.info(`Shutdown hook succeeded`); } catch (error) { logger.error(`Shutdown hook failed, ${error}`); @@ -58,8 +62,10 @@ export class BackendLifecycleImpl implements RootLifecycleService { /** * Allows plugins to register shutdown hooks that are run when the process is about to exit. - * @public */ -export const rootLifecycleFactory = createServiceFactory({ + * + * @public + */ +export const rootLifecycleServiceFactory = createServiceFactory({ service: coreServices.rootLifecycle, deps: { logger: coreServices.rootLogger, diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/index.ts b/packages/backend-app-api/src/services/implementations/rootLogger/index.ts index ce5816e6fa..366cd53163 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/index.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { rootLoggerFactory } from './rootLoggerFactory'; +export { rootLoggerServiceFactory } from './rootLoggerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts similarity index 96% rename from packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts rename to packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts index 1c2214b98c..11bbd58050 100644 --- a/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/rootLogger/rootLoggerServiceFactory.ts @@ -23,7 +23,7 @@ import { transports, format } from 'winston'; import { createConfigSecretEnumerator } from '../../../config'; /** @public */ -export const rootLoggerFactory = createServiceFactory({ +export const rootLoggerServiceFactory = createServiceFactory({ service: coreServices.rootLogger, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/scheduler/index.ts b/packages/backend-app-api/src/services/implementations/scheduler/index.ts index 8b84906b5b..8b67006a4d 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/index.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { schedulerFactory } from './schedulerFactory'; +export { schedulerServiceFactory } from './schedulerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts similarity index 93% rename from packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts rename to packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts index 1aaf4ec71d..7af9de44da 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.test.ts @@ -19,16 +19,16 @@ import { createBackendPlugin, } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; -import { schedulerFactory } from './schedulerFactory'; +import { schedulerServiceFactory } from './schedulerServiceFactory'; describe('schedulerFactory', () => { it('creates sidecar database features', async () => { expect.assertions(3); - const subject = schedulerFactory(); + const subject = schedulerServiceFactory(); const plugin = createBackendPlugin({ - id: 'example', + pluginId: 'example', register(reg) { reg.registerInit({ deps: { diff --git a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts similarity index 95% rename from packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts rename to packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts index 458c5acfd6..4dfe567ccc 100644 --- a/packages/backend-app-api/src/services/implementations/scheduler/schedulerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/scheduler/schedulerServiceFactory.ts @@ -22,7 +22,7 @@ import { import { TaskScheduler } from '@backstage/backend-tasks'; /** @public */ -export const schedulerFactory = createServiceFactory({ +export const schedulerServiceFactory = createServiceFactory({ service: coreServices.scheduler, deps: { plugin: coreServices.pluginMetadata, diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/index.ts b/packages/backend-app-api/src/services/implementations/tokenManager/index.ts index c0685079c4..3ae3d45d2f 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/index.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { tokenManagerFactory } from './tokenManagerFactory'; +export { tokenManagerServiceFactory } from './tokenManagerServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts similarity index 81% rename from packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts rename to packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts index abc62fff69..aca5211e2e 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.test.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.test.ts @@ -14,22 +14,15 @@ * limitations under the License. */ -import { - LoggerService, - ServiceFactory, - TokenManagerService, -} from '@backstage/backend-plugin-api'; +import { LoggerService } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; -import { tokenManagerFactory } from './tokenManagerFactory'; +import { tokenManagerServiceFactory } from './tokenManagerServiceFactory'; describe('tokenManagerFactory', () => { it('should create managers that can share tokens in development', async () => { (process.env as { NODE_ENV?: string }).NODE_ENV = 'development'; - const factory = tokenManagerFactory() as Exclude< - ServiceFactory, - { scope: 'root' } - >; + const factory = tokenManagerServiceFactory() as any; const deps = { config: new ConfigReader({}), logger: { warn() {} } as unknown as LoggerService, diff --git a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts rename to packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts index ae0b402eec..b3726176b6 100644 --- a/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerFactory.ts +++ b/packages/backend-app-api/src/services/implementations/tokenManager/tokenManagerServiceFactory.ts @@ -21,7 +21,7 @@ import { import { ServerTokenManager } from '@backstage/backend-common'; /** @public */ -export const tokenManagerFactory = createServiceFactory({ +export const tokenManagerServiceFactory = createServiceFactory({ service: coreServices.tokenManager, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/services/implementations/urlReader/index.ts b/packages/backend-app-api/src/services/implementations/urlReader/index.ts index 5da0ef4049..6a4b9f65be 100644 --- a/packages/backend-app-api/src/services/implementations/urlReader/index.ts +++ b/packages/backend-app-api/src/services/implementations/urlReader/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { urlReaderFactory } from './urlReaderFactory'; +export { urlReaderServiceFactory } from './urlReaderServiceFactory'; diff --git a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts similarity index 94% rename from packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts rename to packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts index 1b52ce9604..83e594aa0b 100644 --- a/packages/backend-app-api/src/services/implementations/urlReader/urlReaderFactory.ts +++ b/packages/backend-app-api/src/services/implementations/urlReader/urlReaderServiceFactory.ts @@ -21,7 +21,7 @@ import { } from '@backstage/backend-plugin-api'; /** @public */ -export const urlReaderFactory = createServiceFactory({ +export const urlReaderServiceFactory = createServiceFactory({ service: coreServices.urlReader, deps: { config: coreServices.config, diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index ce17398a79..2a8fa1e720 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -20,16 +20,19 @@ import { coreServices, ServiceRef, } from '@backstage/backend-plugin-api'; -import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleFactory'; +import { BackendLifecycleImpl } from '../services/implementations/rootLifecycle/rootLifecycleServiceFactory'; import { BackendRegisterInit, EnumerableServiceHolder, ServiceOrExtensionPoint, } from './types'; +// Direct internal import to avoid duplication +// eslint-disable-next-line @backstage/no-forbidden-package-imports +import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; export class BackendInitializer { - #started = false; - #features = new Map(); + #startPromise?: Promise; + #features = new Array(); #registerInits = new Array(); #extensionPoints = new Map, unknown>(); #serviceHolder: EnumerableServiceHolder; @@ -74,19 +77,52 @@ export class BackendInitializer { return Object.fromEntries(result); } - add(feature: BackendFeature, options?: TOptions) { - if (this.#started) { + add(feature: BackendFeature) { + if (this.#startPromise) { throw new Error('feature can not be added after the backend has started'); } - this.#features.set(feature, options); + if (feature.$$type !== '@backstage/BackendFeature') { + throw new Error( + `Failed to add feature, invalid type '${feature.$$type}'`, + ); + } + const internalFeature = feature as InternalBackendFeature; + if (internalFeature.version !== 'v1') { + throw new Error( + `Failed to add feature, invalid version '${internalFeature.version}'`, + ); + } + this.#features.push(internalFeature); } async start(): Promise { - if (this.#started) { + if (this.#startPromise) { throw new Error('Backend has already started'); } - this.#started = true; + const exitHandler = async () => { + process.removeListener('SIGTERM', exitHandler); + process.removeListener('SIGINT', exitHandler); + process.removeListener('beforeExit', exitHandler); + + try { + await this.stop(); + process.exit(0); + } catch (error) { + console.error(error); + process.exit(1); + } + }; + + process.addListener('SIGTERM', exitHandler); + process.addListener('SIGINT', exitHandler); + process.addListener('beforeExit', exitHandler); + + this.#startPromise = this.#doStart(); + await this.#startPromise; + } + + async #doStart(): Promise { // Initialize all root scoped services for (const ref of this.#serviceHolder.getServiceRefs()) { if (ref.scope === 'root') { @@ -95,50 +131,39 @@ export class BackendInitializer { } // Initialize all features - for (const [feature] of this.#features) { - const provides = new Set>(); + for (const feature of this.#features) { + for (const r of feature.getRegistrations()) { + const provides = new Set>(); - let registerInit: BackendRegisterInit | undefined = undefined; + if (r.type === 'plugin') { + for (const [extRef, extImpl] of r.extensionPoints) { + if (this.#extensionPoints.has(extRef)) { + throw new Error( + `ExtensionPoint with ID '${extRef.id}' is already registered`, + ); + } + this.#extensionPoints.set(extRef, extImpl); + provides.add(extRef); + } + } - feature.register({ - registerExtensionPoint: (extensionPointRef, impl) => { - if (registerInit) { - throw new Error('registerExtensionPoint called after registerInit'); - } - if (this.#extensionPoints.has(extensionPointRef)) { - throw new Error(`API ${extensionPointRef.id} already registered`); - } - this.#extensionPoints.set(extensionPointRef, impl); - provides.add(extensionPointRef); - }, - registerInit: registerOptions => { - if (registerInit) { - throw new Error('registerInit must only be called once'); - } - registerInit = { - id: feature.id, - provides, - consumes: new Set(Object.values(registerOptions.deps)), - deps: registerOptions.deps, - init: registerOptions.init as BackendRegisterInit['init'], - }; - }, - }); - - if (!registerInit) { - throw new Error( - `registerInit was not called by register in ${feature.id}`, - ); + this.#registerInits.push({ + id: r.type === 'plugin' ? r.pluginId : `${r.pluginId}.${r.moduleId}`, + provides, + consumes: new Set(Object.values(r.init.deps)), + init: r.init, + }); } - - this.#registerInits.push(registerInit); } const orderedRegisterResults = this.#resolveInitOrder(this.#registerInits); for (const registerInit of orderedRegisterResults) { - const deps = await this.#getInitDeps(registerInit.deps, registerInit.id); - await registerInit.init(deps); + const deps = await this.#getInitDeps( + registerInit.init.deps, + registerInit.id, + ); + await registerInit.init.func(deps); } } @@ -177,9 +202,10 @@ export class BackendInitializer { } async stop(): Promise { - if (!this.#started) { + if (!this.#startPromise) { return; } + await this.#startPromise; const lifecycleService = await this.#serviceHolder.get( coreServices.rootLifecycle, diff --git a/packages/backend-app-api/src/wiring/ServiceRegistry.ts b/packages/backend-app-api/src/wiring/ServiceRegistry.ts index 68dff3f7c3..b5b55f67cf 100644 --- a/packages/backend-app-api/src/wiring/ServiceRegistry.ts +++ b/packages/backend-app-api/src/wiring/ServiceRegistry.ts @@ -18,36 +18,66 @@ import { ServiceFactory, ServiceRef, coreServices, + createServiceFactory, } from '@backstage/backend-plugin-api'; import { stringifyError } from '@backstage/errors'; import { EnumerableServiceHolder } from './types'; +// Direct internal import to avoid duplication +// eslint-disable-next-line @backstage/no-forbidden-package-imports +import { InternalServiceFactory } from '@backstage/backend-plugin-api/src/services/system/types'; /** * Keep in sync with `@backstage/backend-plugin-api/src/services/system/types.ts` * @internal */ -export type InternalServiceRef = ServiceRef & { +export type InternalServiceRef = ServiceRef & { __defaultFactory?: ( - service: ServiceRef, - ) => Promise | (() => ServiceFactory)>; + service: ServiceRef, + ) => Promise ServiceFactory)>; }; +function toInternalServiceFactory( + factory: ServiceFactory, +): InternalServiceFactory { + const f = factory as InternalServiceFactory; + if (f.$$type !== '@backstage/ServiceFactory') { + throw new Error(`Invalid service factory, bad type '${f.$$type}'`); + } + if (f.version !== 'v1') { + throw new Error(`Invalid service factory, bad version '${f.version}'`); + } + return f; +} + +const pluginMetadataServiceFactory = createServiceFactory( + (options: { pluginId: string }) => ({ + service: coreServices.pluginMetadata, + deps: {}, + factory: async () => ({ getId: () => options.pluginId }), + }), +); + export class ServiceRegistry implements EnumerableServiceHolder { - readonly #providedFactories: Map; - readonly #loadedDefaultFactories: Map>; + readonly #providedFactories: Map; + readonly #loadedDefaultFactories: Map< + Function, + Promise + >; readonly #implementations: Map< - ServiceFactory, + InternalServiceFactory, { context: Promise; byPlugin: Map>; } >; readonly #rootServiceImplementations = new Map< - ServiceFactory, + InternalServiceFactory, Promise >(); - constructor(factories: Array>) { - this.#providedFactories = new Map(factories.map(f => [f.service.id, f])); + constructor(factories: Array) { + this.#providedFactories = new Map( + factories.map(sf => [sf.service.id, toInternalServiceFactory(sf)]), + ); this.#loadedDefaultFactories = new Map(); this.#implementations = new Map(); } @@ -55,23 +85,19 @@ export class ServiceRegistry implements EnumerableServiceHolder { #resolveFactory( ref: ServiceRef, pluginId: string, - ): Promise | undefined { + ): Promise | undefined { // Special case handling of the plugin metadata service, generating a custom factory for it each time if (ref.id === coreServices.pluginMetadata.id) { - return Promise.resolve< - ServiceFactory - >({ - scope: 'plugin', - service: coreServices.pluginMetadata, - deps: {}, - factory: async () => ({ getId: () => pluginId }), - }); + return Promise.resolve( + toInternalServiceFactory(pluginMetadataServiceFactory({ pluginId })), + ); } - let resolvedFactory: Promise | ServiceFactory | undefined = - this.#providedFactories.get(ref.id); - const { __defaultFactory: defaultFactory } = - ref as InternalServiceRef; + let resolvedFactory: + | Promise + | InternalServiceFactory + | undefined = this.#providedFactories.get(ref.id); + const { __defaultFactory: defaultFactory } = ref as InternalServiceRef; if (!resolvedFactory && !defaultFactory) { return undefined; } @@ -82,8 +108,8 @@ export class ServiceRegistry implements EnumerableServiceHolder { loadedFactory = Promise.resolve() .then(() => defaultFactory!(ref)) .then(f => - typeof f === 'function' ? f() : f, - ) as Promise; + toInternalServiceFactory(typeof f === 'function' ? f() : f), + ); this.#loadedDefaultFactories.set(defaultFactory!, loadedFactory); } resolvedFactory = loadedFactory.catch(error => { @@ -100,7 +126,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { return Promise.resolve(resolvedFactory); } - #checkForMissingDeps(factory: ServiceFactory, pluginId: string) { + #checkForMissingDeps(factory: InternalServiceFactory, pluginId: string) { const missingDeps = Object.values(factory.deps).filter(ref => { if (ref.id === coreServices.pluginMetadata.id) { return false; @@ -109,7 +135,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { return false; } - return !(ref as InternalServiceRef).__defaultFactory; + return !(ref as InternalServiceRef).__defaultFactory; }); if (missingDeps.length) { @@ -126,7 +152,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { get(ref: ServiceRef, pluginId: string): Promise | undefined { return this.#resolveFactory(ref, pluginId)?.then(factory => { - if (factory.scope === 'root') { + if (factory.service.scope === 'root') { let existing = this.#rootServiceImplementations.get(factory); if (!existing) { this.#checkForMissingDeps(factory, pluginId); @@ -143,7 +169,7 @@ export class ServiceRegistry implements EnumerableServiceHolder { } existing = Promise.all(rootDeps).then(entries => - factory.factory(Object.fromEntries(entries)), + factory.factory(Object.fromEntries(entries), undefined), ); this.#rootServiceImplementations.set(factory, existing); } diff --git a/packages/backend-app-api/src/wiring/index.ts b/packages/backend-app-api/src/wiring/index.ts index 6e0fb272ae..00e4a9d4b4 100644 --- a/packages/backend-app-api/src/wiring/index.ts +++ b/packages/backend-app-api/src/wiring/index.ts @@ -14,9 +14,5 @@ * limitations under the License. */ -export type { - Backend, - CreateSpecializedBackendOptions, - ServiceOrExtensionPoint, -} from './types'; +export type { Backend, CreateSpecializedBackendOptions } from './types'; export { createSpecializedBackend } from './createSpecializedBackend'; diff --git a/packages/backend-app-api/src/wiring/types.ts b/packages/backend-app-api/src/wiring/types.ts index d3c4fc48c7..2a91bf46b9 100644 --- a/packages/backend-app-api/src/wiring/types.ts +++ b/packages/backend-app-api/src/wiring/types.ts @@ -34,8 +34,10 @@ export interface BackendRegisterInit { id: string; consumes: Set; provides: Set; - deps: { [name: string]: ServiceOrExtensionPoint }; - init: (deps: { [name: string]: unknown }) => Promise; + init: { + deps: { [name: string]: ServiceOrExtensionPoint }; + func: (deps: { [name: string]: unknown }) => Promise; + }; } /** diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index d9bbd21600..1a495ff771 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/backend-common +## 0.18.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- d31d8e00b3: Updated to work with the new `type: 'pem'` with `createHttpServer` from `@backstage/backend-app-api` +- 0ff03319be: Updated usage of `createBackendPlugin`. +- f60cca9da1: The `DatabaseManager.forPlugin` method now accepts additional service dependencies. There is no need to update existing code to pass these dependencies. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-dev-utils@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.18.2-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + ## 0.18.2-next.0 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index b03d6ec866..d21ef30a0b 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -13,9 +13,9 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { BitbucketCloudIntegration } from '@backstage/integration'; import { BitbucketIntegration } from '@backstage/integration'; import { BitbucketServerIntegration } from '@backstage/integration'; -import { CacheClient } from '@backstage/backend-plugin-api'; -import { CacheClientOptions } from '@backstage/backend-plugin-api'; -import { CacheClientSetOptions } from '@backstage/backend-plugin-api'; +import { CacheService as CacheClient } from '@backstage/backend-plugin-api'; +import { CacheServiceOptions as CacheClientOptions } from '@backstage/backend-plugin-api'; +import { CacheServiceSetOptions as CacheClientSetOptions } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import cors from 'cors'; @@ -32,14 +32,15 @@ import { IdentityService } from '@backstage/backend-plugin-api'; import { isChildPath } from '@backstage/cli-common'; import { Knex } from 'knex'; import { KubeConfig } from '@kubernetes/client-node'; +import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoadConfigOptionsRemote } from '@backstage/config-loader'; import { Logger } from 'winston'; import { LoggerService } from '@backstage/backend-plugin-api'; import { MergeResult } from 'isomorphic-git'; import { PermissionsService } from '@backstage/backend-plugin-api'; -import { CacheService as PluginCacheManager } from '@backstage/backend-plugin-api'; import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api'; import { DiscoveryService as PluginEndpointDiscovery } from '@backstage/backend-plugin-api'; +import { PluginMetadataService } from '@backstage/backend-plugin-api'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; import { ReadCommitResult } from 'isomorphic-git'; @@ -197,6 +198,11 @@ export type CacheManagerOptions = { onError?: (err: Error) => void; }; +// @public (undocumented) +export function cacheToPluginCacheManager( + cache: CacheClient, +): PluginCacheManager; + // @public export const coloredFormat: winston.Logform.Format; @@ -232,6 +238,10 @@ export class Contexts { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ): Knex; // @public @@ -252,7 +262,13 @@ export function createStatusCheckRouter(options: { // @public export class DatabaseManager { - forPlugin(pluginId: string): PluginDatabaseManager; + forPlugin( + pluginId: string, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, + ): PluginDatabaseManager; static fromConfig( config: Config, options?: DatabaseManagerOptions, @@ -516,7 +532,7 @@ export const legacyPlugin: ( default: LegacyCreateRouter< TransformedEnv< { - cache: PluginCacheManager; + cache: CacheClient; config: ConfigService; database: PluginDatabaseManager; discovery: PluginEndpointDiscovery; @@ -529,6 +545,7 @@ export const legacyPlugin: ( }, { logger: (log: LoggerService) => Logger; + cache: (cache: CacheClient) => PluginCacheManager; } > >; @@ -569,7 +586,11 @@ export function makeLegacyPlugin< // @public export function notFoundHandler(): RequestHandler; -export { PluginCacheManager }; +// @public (undocumented) +export interface PluginCacheManager { + // (undocumented) + getClient(options?: CacheClientOptions): CacheClient; +} export { PluginDatabaseManager }; diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 69f48c0a82..9619ef25f8 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.18.2-next.0", + "version": "0.18.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -35,6 +35,7 @@ }, "dependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/config": "workspace:^", diff --git a/packages/backend-common/src/cache/CacheClient.test.ts b/packages/backend-common/src/cache/CacheClient.test.ts index 8a5779550a..245d8687c9 100644 --- a/packages/backend-common/src/cache/CacheClient.test.ts +++ b/packages/backend-common/src/cache/CacheClient.test.ts @@ -32,7 +32,7 @@ describe('CacheClient', () => { describe('CacheClient.get', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.get(key); @@ -41,7 +41,7 @@ describe('CacheClient', () => { }); it('calls client with normalized key (very long key)', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'x'.repeat(251); await sut.get(key); @@ -53,7 +53,7 @@ describe('CacheClient', () => { }); it('rejects on underlying error', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.get = jest.fn().mockRejectedValue(expectedError); @@ -61,7 +61,7 @@ describe('CacheClient', () => { }); it('resolves what underlying client resolves', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedValue = 'some value'; client.get = jest.fn().mockResolvedValue(expectedValue); @@ -73,7 +73,7 @@ describe('CacheClient', () => { describe('CacheClient.set', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.set(key, {}); @@ -84,7 +84,7 @@ describe('CacheClient', () => { }); it('passes ttl to client when given', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedTtl = 3600; await sut.set('someKey', {}, { ttl: expectedTtl }); @@ -95,7 +95,7 @@ describe('CacheClient', () => { }); it('rejects on underlying error if configured', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.set = jest.fn().mockRejectedValue(expectedError); @@ -105,7 +105,7 @@ describe('CacheClient', () => { describe('CacheClient.delete', () => { it('calls client with normalized key', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const key = 'somekey'; await sut.delete(key); @@ -116,11 +116,35 @@ describe('CacheClient', () => { }); it('rejects on underlying error if configured', async () => { - const sut = new DefaultCacheClient({ client }); + const sut = new DefaultCacheClient(client, () => client, {}); const expectedError = new Error('Some runtime error'); client.delete = jest.fn().mockRejectedValue(expectedError); return expect(sut.delete('someKey')).rejects.toEqual(expectedError); }); }); + + describe('CacheClient.withOptions', () => { + it('merges together options to create a new instance', async () => { + const factory = jest.fn(); + const sut = new DefaultCacheClient(client, factory, { foo: 1 } as any); + expect(factory).not.toHaveBeenCalled(); + + const sutA = await sut.withOptions({}); + expect(factory).toHaveBeenLastCalledWith({ foo: 1 }); + + const sutA2 = await sutA.withOptions({ bar: 2 } as any); + expect(factory).toHaveBeenCalledWith({ foo: 1, bar: 2 }); + + await sutA2.withOptions({ foo: 3 } as any); + expect(factory).toHaveBeenCalledWith({ foo: 3, bar: 2 }); + + // calling .withOptions should not mutate state + const sutB = await sut.withOptions({ foo: 2 } as any); + expect(factory).toHaveBeenLastCalledWith({ foo: 2 }); + + await sutB.withOptions({ bar: 3 } as any); + expect(factory).toHaveBeenLastCalledWith({ foo: 2, bar: 3 }); + }); + }); }); diff --git a/packages/backend-common/src/cache/CacheClient.ts b/packages/backend-common/src/cache/CacheClient.ts index 47cb786f14..24ee7ac455 100644 --- a/packages/backend-common/src/cache/CacheClient.ts +++ b/packages/backend-common/src/cache/CacheClient.ts @@ -15,50 +15,64 @@ */ import { - CacheClient, - CacheClientSetOptions, + CacheService, + CacheServiceOptions, + CacheServiceSetOptions, } from '@backstage/backend-plugin-api'; import { JsonValue } from '@backstage/types'; import { createHash } from 'crypto'; import Keyv from 'keyv'; -export type { - CacheClient, - CacheClientSetOptions, -} from '@backstage/backend-plugin-api'; - -type CacheClientArgs = { - client: Keyv; -}; +export type CacheClientFactory = (options: CacheServiceOptions) => Keyv; /** - * A basic, concrete implementation of the CacheClient, suitable for almost + * A basic, concrete implementation of the CacheService, suitable for almost * all uses in Backstage. */ -export class DefaultCacheClient implements CacheClient { - private readonly client: Keyv; +export class DefaultCacheClient implements CacheService { + #client: Keyv; + #clientFactory: CacheClientFactory; + #options: CacheServiceOptions; - constructor({ client }: CacheClientArgs) { - this.client = client; + constructor( + client: Keyv, + clientFactory: CacheClientFactory, + options: CacheServiceOptions, + ) { + this.#client = client; + this.#clientFactory = clientFactory; + this.#options = options; } - async get(key: string): Promise { + async get( + key: string, + ): Promise { const k = this.getNormalizedKey(key); - return await this.client.get(k); + const value = await this.#client.get(k); + return value as TValue | undefined; } async set( key: string, value: JsonValue, - opts: CacheClientSetOptions = {}, + opts: CacheServiceSetOptions = {}, ): Promise { const k = this.getNormalizedKey(key); - await this.client.set(k, value, opts.ttl); + await this.#client.set(k, value, opts.ttl); } async delete(key: string): Promise { const k = this.getNormalizedKey(key); - await this.client.delete(k); + await this.#client.delete(k); + } + + withOptions(options: CacheServiceOptions): CacheService { + const newOptions = { ...this.#options, ...options }; + return new DefaultCacheClient( + this.#clientFactory(newOptions), + this.#clientFactory, + newOptions, + ); } /** diff --git a/packages/backend-common/src/cache/CacheManager.test.ts b/packages/backend-common/src/cache/CacheManager.test.ts index 50b775af25..3239be4d0e 100644 --- a/packages/backend-common/src/cache/CacheManager.test.ts +++ b/packages/backend-common/src/cache/CacheManager.test.ts @@ -94,7 +94,7 @@ describe('CacheManager', () => { const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; expect(realClient.on).toHaveBeenCalledWith('error', expect.any(Function)); }); @@ -233,7 +233,7 @@ describe('CacheManager', () => { // Retrieve the error handler attached to the cache client. const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; const realOnError = realClient.on as jest.Mock; const realHandler = realOnError.mock.calls.splice(-1)[0][1]; @@ -259,7 +259,7 @@ describe('CacheManager', () => { // Retrieve the error handler attached to the cache client. const client = DefaultCacheClient as jest.Mock; const mockCalls = client.mock.calls.splice(-1); - const realClient = mockCalls[0][0].client as Keyv; + const realClient = mockCalls[0][0] as Keyv; const realOnError = realClient.on as jest.Mock; const realHandler = realOnError.mock.calls.splice(-1)[0][1]; diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts index 4f7f5403a8..12ece42854 100644 --- a/packages/backend-common/src/cache/CacheManager.ts +++ b/packages/backend-common/src/cache/CacheManager.ts @@ -18,9 +18,13 @@ import { Config } from '@backstage/config'; import Keyv from 'keyv'; import KeyvMemcache from '@keyv/memcache'; import KeyvRedis from '@keyv/redis'; -import { LoggerService } from '@backstage/backend-plugin-api'; +import { + CacheService, + CacheServiceOptions, + LoggerService, +} from '@backstage/backend-plugin-api'; import { getRootLogger } from '../logging'; -import { DefaultCacheClient, CacheClient } from './CacheClient'; +import { DefaultCacheClient } from './CacheClient'; import { NoStore } from './NoStore'; import { CacheManagerOptions, PluginCacheManager } from './types'; @@ -99,23 +103,32 @@ export class CacheManager { */ forPlugin(pluginId: string): PluginCacheManager { return { - getClient: (opts = {}): CacheClient => { - const concreteClient = this.getClientWithTtl(pluginId, opts.defaultTtl); + getClient: (defaultOptions = {}) => { + const clientFactory = (options: CacheServiceOptions) => { + const concreteClient = this.getClientWithTtl( + pluginId, + options.defaultTtl, + ); - // Always provide an error handler to avoid stopping the process. - concreteClient.on('error', (err: Error) => { - // In all cases, just log the error. - this.logger.error('Failed to create cache client', err); + // Always provide an error handler to avoid stopping the process. + concreteClient.on('error', (err: Error) => { + // In all cases, just log the error. + this.logger.error('Failed to create cache client', err); - // Invoke any custom error handler if provided. - if (typeof this.errorHandler === 'function') { - this.errorHandler(err); - } - }); + // Invoke any custom error handler if provided. + if (typeof this.errorHandler === 'function') { + this.errorHandler(err); + } + }); - return new DefaultCacheClient({ - client: concreteClient, - }); + return concreteClient; + }; + + return new DefaultCacheClient( + clientFactory(defaultOptions), + clientFactory, + defaultOptions, + ); }, }; } @@ -164,3 +177,12 @@ export class CacheManager { }); } } + +/** @public */ +export function cacheToPluginCacheManager( + cache: CacheService, +): PluginCacheManager { + return { + getClient: (opts: CacheServiceOptions) => cache.withOptions(opts), + }; +} diff --git a/packages/backend-common/src/cache/index.ts b/packages/backend-common/src/cache/index.ts index 26e6c102d8..0187aa45d5 100644 --- a/packages/backend-common/src/cache/index.ts +++ b/packages/backend-common/src/cache/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -export type { CacheClient, CacheClientSetOptions } from './CacheClient'; -export { CacheManager } from './CacheManager'; +export { CacheManager, cacheToPluginCacheManager } from './CacheManager'; export type { + CacheClient, + CacheClientSetOptions, PluginCacheManager, CacheManagerOptions, CacheClientOptions, diff --git a/packages/backend-common/src/cache/types.ts b/packages/backend-common/src/cache/types.ts index eeeafde5b6..93fa0ac77c 100644 --- a/packages/backend-common/src/cache/types.ts +++ b/packages/backend-common/src/cache/types.ts @@ -15,10 +15,15 @@ */ import { LoggerService } from '@backstage/backend-plugin-api'; +import { + CacheService, + CacheServiceOptions, +} from '@backstage/backend-plugin-api'; export type { - CacheService as PluginCacheManager, - CacheClientOptions, + CacheService as CacheClient, + CacheServiceSetOptions as CacheClientSetOptions, + CacheServiceOptions as CacheClientOptions, } from '@backstage/backend-plugin-api'; /** @@ -38,3 +43,10 @@ export type CacheManagerOptions = { */ onError?: (err: Error) => void; }; + +/** + * @public + */ +export interface PluginCacheManager { + getClient(options?: CacheServiceOptions): CacheService; +} diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index 5a497fff29..08979a92f8 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -29,7 +29,11 @@ import { } from './connection'; import { PluginDatabaseManager } from './types'; import path from 'path'; -import { LoggerService } from '@backstage/backend-plugin-api'; +import { + LifecycleService, + LoggerService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; import { stringifyError } from '@backstage/errors'; /** @@ -94,12 +98,18 @@ export class DatabaseManager { * should be unique as they are used to look up database config overrides under * `backend.database.plugin`. */ - forPlugin(pluginId: string): PluginDatabaseManager { + forPlugin( + pluginId: string, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, + ): PluginDatabaseManager { const _this = this; return { getClient(): Promise { - return _this.getDatabase(pluginId); + return _this.getDatabase(pluginId, deps); }, migrations: { skip: false, @@ -307,7 +317,13 @@ export class DatabaseManager { * @returns Promise which resolves to a scoped Knex database client for a * plugin */ - private async getDatabase(pluginId: string): Promise { + private async getDatabase( + pluginId: string, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, + ): Promise { if (this.databaseCache.has(pluginId)) { return this.databaseCache.get(pluginId)!; } @@ -351,6 +367,7 @@ export class DatabaseManager { const client = createDatabaseClient( pluginConfig, databaseClientOverrides, + deps, ); this.startKeepaliveLoop(pluginId, client); return client; diff --git a/packages/backend-common/src/database/connection.ts b/packages/backend-common/src/database/connection.ts index 5f487886b4..ff10d349dd 100644 --- a/packages/backend-common/src/database/connection.ts +++ b/packages/backend-common/src/database/connection.ts @@ -22,6 +22,10 @@ import { mergeDatabaseConfig } from './config'; import { DatabaseConnector } from './types'; import { mysqlConnector, pgConnector, sqlite3Connector } from './connectors'; +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; type DatabaseClient = | 'pg' @@ -55,11 +59,15 @@ const ConnectorMapping: Record = { export function createDatabaseClient( dbConfig: Config, overrides?: Partial, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ) { const client: DatabaseClient = dbConfig.getString('client'); return ( - ConnectorMapping[client]?.createClient(dbConfig, overrides) ?? + ConnectorMapping[client]?.createClient(dbConfig, overrides, deps) ?? knexFactory(mergeDatabaseConfig(dbConfig.get(), overrides)) ); } diff --git a/packages/backend-common/src/database/connectors/sqlite3.ts b/packages/backend-common/src/database/connectors/sqlite3.ts index 6426005f0e..3cb0f57de6 100644 --- a/packages/backend-common/src/database/connectors/sqlite3.ts +++ b/packages/backend-common/src/database/connectors/sqlite3.ts @@ -18,8 +18,13 @@ import { Config } from '@backstage/config'; import { ensureDirSync } from 'fs-extra'; import knexFactory, { Knex } from 'knex'; import path from 'path'; +import { DevDataStore } from '@backstage/backend-dev-utils'; import { mergeDatabaseConfig } from '../config'; import { DatabaseConnector } from '../types'; +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; /** * Creates a knex SQLite3 database connection @@ -30,22 +35,63 @@ import { DatabaseConnector } from '../types'; export function createSqliteDatabaseClient( dbConfig: Config, overrides?: Knex.Config, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, ) { const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides); + const connConfig = knexConfig.connection as Knex.Sqlite3ConnectionConfig; + + const filename = connConfig.filename ?? ':memory:'; // If storage on disk is used, ensure that the directory exists - if ( - (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename && - (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename !== - ':memory:' - ) { - const { filename } = knexConfig.connection as Knex.Sqlite3ConnectionConfig; + if (filename !== ':memory:') { const directory = path.dirname(filename); - ensureDirSync(directory); } - const database = knexFactory(knexConfig); + let database: Knex; + + if (deps && filename === ':memory:') { + // The dev store is used during watch mode to store and restore the database + // across reloads. It is only available when running the backend through + // `backstage-cli package start`. + const devStore = DevDataStore.get(); + + if (devStore) { + const dataKey = `sqlite3-db-${deps.pluginMetadata.getId()}`; + + const connectionLoader = async () => { + // If seed data is available, use it tconnectionLoader restore the database + const { data: seedData } = await devStore.load(dataKey); + + return { + ...(knexConfig.connection as Knex.Sqlite3ConnectionConfig), + filename: seedData ?? ':memory:', + }; + }; + + database = knexFactory({ + ...knexConfig, + connection: Object.assign(connectionLoader, { + // This is a workaround for the knex SQLite driver always warning when using a config loader + filename: ':memory:', + }), + }); + + // If the dev store is available we save the database state on shutdown + deps.lifecycle.addShutdownHook(async () => { + const connection = await database.client.acquireConnection(); + const data = connection.serialize(); + await devStore.save(dataKey, data); + }); + } else { + database = knexFactory(knexConfig); + } + } else { + database = knexFactory(knexConfig); + } database.client.pool.on('createSuccess', (_eventId: any, resource: any) => { resource.run('PRAGMA foreign_keys = ON', () => {}); diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts index 2d59cf636e..621bcc676b 100644 --- a/packages/backend-common/src/database/types.ts +++ b/packages/backend-common/src/database/types.ts @@ -14,6 +14,10 @@ * limitations under the License. */ +import { + LifecycleService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { Knex } from 'knex'; @@ -26,7 +30,14 @@ export interface DatabaseConnector { /** * createClient provides an instance of a knex database connector. */ - createClient(dbConfig: Config, overrides?: Partial): Knex; + createClient( + dbConfig: Config, + overrides?: Partial, + deps?: { + lifecycle: LifecycleService; + pluginMetadata: PluginMetadataService; + }, + ): Knex; /** * createNameOverride provides a partial knex config sufficient to override a * database name. diff --git a/packages/backend-common/src/legacy.ts b/packages/backend-common/src/legacy.ts index 30e7dd9dc5..408966f3bc 100644 --- a/packages/backend-common/src/legacy.ts +++ b/packages/backend-common/src/legacy.ts @@ -20,6 +20,7 @@ import { ServiceRef, } from '@backstage/backend-plugin-api'; import { RequestHandler } from 'express'; +import { cacheToPluginCacheManager } from './cache'; import { loggerToWinstonLogger } from './logging'; /** @@ -60,7 +61,7 @@ export function makeLegacyPlugin< }>, ) => { const compatPlugin = createBackendPlugin({ - id: name, + pluginId: name, register(env) { env.registerInit({ deps: { ...envMapping, _router: coreServices.httpRouter }, @@ -119,5 +120,6 @@ export const legacyPlugin = makeLegacyPlugin( }, { logger: log => loggerToWinstonLogger(log), + cache: cache => cacheToPluginCacheManager(cache), }, ); diff --git a/packages/backend-common/src/logging/loggerToWinstonLogger.ts b/packages/backend-common/src/logging/loggerToWinstonLogger.ts index f15bd5be81..4ba88358d2 100644 --- a/packages/backend-common/src/logging/loggerToWinstonLogger.ts +++ b/packages/backend-common/src/logging/loggerToWinstonLogger.ts @@ -15,6 +15,7 @@ */ import { LoggerService } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import { Logger as WinstonLogger, createLogger } from 'winston'; import Transport, { TransportStreamOptions } from 'winston-transport'; @@ -31,7 +32,7 @@ class BackstageLoggerTransport extends Transport { callback(); return; } - const { level, message, ...meta } = info as { [name: string]: unknown }; + const { level, message, ...meta } = info as JsonObject; switch (level) { case 'error': this.backstageLogger.error(String(message), meta); diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index fdd3c7dbc8..629173f96e 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -202,7 +202,7 @@ describe('Git', () => { await git.clone({ url, dir }); const { onAuth } = ( - isomorphic.clone as unknown as jest.Mock + isomorphic.clone as unknown as jest.Mock<(typeof isomorphic)['clone']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); @@ -315,7 +315,7 @@ describe('Git', () => { await git.fetch({ remote, dir }); const { onAuth } = ( - isomorphic.fetch as unknown as jest.Mock + isomorphic.fetch as unknown as jest.Mock<(typeof isomorphic)['fetch']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); @@ -486,7 +486,7 @@ describe('Git', () => { await git.push({ remote, dir, remoteRef, force }); const { onAuth } = ( - isomorphic.push as unknown as jest.Mock + isomorphic.push as unknown as jest.Mock<(typeof isomorphic)['push']> ).mock.calls[0][0]!; expect(onAuth()).toEqual(auth); diff --git a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts index f74dcd9b64..f577017b77 100644 --- a/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts +++ b/packages/backend-common/src/service/lib/ServiceBuilderImpl.ts @@ -102,7 +102,7 @@ export class ServiceBuilderImpl implements ServiceBuilder { this.serverOptions.https = { certificate: { ...settings.certificate, - type: 'plain', + type: 'pem', }, }; } diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index e91a1dede3..89f3ee25c6 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/backend-defaults +## 0.1.7-next.2 + +### Patch Changes + +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 1d9e7823e5..2d92d15ab8 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.7-next.0", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-defaults/src/CreateBackend.test.ts b/packages/backend-defaults/src/CreateBackend.test.ts index 2cfb92c3a6..8d56cd0986 100644 --- a/packages/backend-defaults/src/CreateBackend.test.ts +++ b/packages/backend-defaults/src/CreateBackend.test.ts @@ -143,7 +143,7 @@ describe('createBackend', () => { expect.assertions(3); backend.add( createBackendPlugin({ - id: 'test', + pluginId: 'test', register(reg) { reg.registerInit({ deps: { diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index e6b5a15336..480f365216 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -16,22 +16,22 @@ import { Backend, - cacheFactory, - configFactory, + cacheServiceFactory, + configServiceFactory, createSpecializedBackend, - databaseFactory, - discoveryFactory, - httpRouterFactory, - rootHttpRouterFactory, - lifecycleFactory, - rootLifecycleFactory, - loggerFactory, - permissionsFactory, - rootLoggerFactory, - schedulerFactory, - tokenManagerFactory, - urlReaderFactory, - identityFactory, + databaseServiceFactory, + discoveryServiceFactory, + httpRouterServiceFactory, + rootHttpRouterServiceFactory, + lifecycleServiceFactory, + rootLifecycleServiceFactory, + loggerServiceFactory, + permissionsServiceFactory, + rootLoggerServiceFactory, + schedulerServiceFactory, + tokenManagerServiceFactory, + urlReaderServiceFactory, + identityServiceFactory, } from '@backstage/backend-app-api'; import { ServiceFactory, @@ -40,25 +40,25 @@ import { } from '@backstage/backend-plugin-api'; // Internal import of the type to avoid needing to export this. -// eslint-disable-next-line monorepo/no-internal-import +// eslint-disable-next-line @backstage/no-forbidden-package-imports import type { InternalSharedBackendEnvironment } from '@backstage/backend-plugin-api/src/wiring/createSharedEnvironment'; export const defaultServiceFactories = [ - cacheFactory(), - configFactory(), - databaseFactory(), - discoveryFactory(), - httpRouterFactory(), - identityFactory(), - lifecycleFactory(), - loggerFactory(), - permissionsFactory(), - rootHttpRouterFactory(), - rootLifecycleFactory(), - rootLoggerFactory(), - schedulerFactory(), - tokenManagerFactory(), - urlReaderFactory(), + cacheServiceFactory(), + configServiceFactory(), + databaseServiceFactory(), + discoveryServiceFactory(), + httpRouterServiceFactory(), + identityServiceFactory(), + lifecycleServiceFactory(), + loggerServiceFactory(), + permissionsServiceFactory(), + rootHttpRouterServiceFactory(), + rootLifecycleServiceFactory(), + rootLoggerServiceFactory(), + schedulerServiceFactory(), + tokenManagerServiceFactory(), + urlReaderServiceFactory(), ]; /** diff --git a/packages/backend-dev-utils/.eslintrc.js b/packages/backend-dev-utils/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/backend-dev-utils/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md new file mode 100644 index 0000000000..9acf8cf15f --- /dev/null +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -0,0 +1,7 @@ +# @backstage/backend-dev-utils + +## 0.1.0-next.0 + +### Minor Changes + +- 9d9cdea117: Introduced a new package for backend development utilities. Similar to how `@backstage/dev-utils` is used in the frontend. diff --git a/packages/backend-dev-utils/README.md b/packages/backend-dev-utils/README.md new file mode 100644 index 0000000000..8acce94cf0 --- /dev/null +++ b/packages/backend-dev-utils/README.md @@ -0,0 +1,5 @@ +# backend-dev-utils + +Welcome to the backend-dev-utils package! + +_This package is experimental._ diff --git a/packages/backend-dev-utils/api-report.md b/packages/backend-dev-utils/api-report.md new file mode 100644 index 0000000000..216311ccd8 --- /dev/null +++ b/packages/backend-dev-utils/api-report.md @@ -0,0 +1,20 @@ +## API Report File for "@backstage/backend-dev-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public +export class DevDataStore { + static get(): DevDataStore | undefined; + load(key: string): Promise<{ + loaded: boolean; + data: T; + }>; + save( + key: string, + data: T, + ): Promise<{ + saved: boolean; + }>; +} +``` diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json new file mode 100644 index 0000000000..6e1cf7d3b0 --- /dev/null +++ b/packages/backend-dev-utils/package.json @@ -0,0 +1,36 @@ +{ + "name": "@backstage/backend-dev-utils", + "version": "0.1.0-next.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" + }, + "backstage": { + "role": "node-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/backend-dev-utils" + }, + "scripts": { + "start": "backstage-cli package start", + "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" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/packages/backend-dev-utils/src/DevDataStore.test.ts b/packages/backend-dev-utils/src/DevDataStore.test.ts new file mode 100644 index 0000000000..2bb3f221ae --- /dev/null +++ b/packages/backend-dev-utils/src/DevDataStore.test.ts @@ -0,0 +1,121 @@ +/* + * Copyright 2023 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 { Serializable, spawn } from 'child_process'; +import { DevDataStore } from './DevDataStore'; +import { BackstageIpcClient } from './ipcClient'; + +function applyIpcTransform(value: Serializable): Promise { + const child = spawn( + 'node', + [ + '--eval', + ` + const listener = msg => { + process.send(msg); + process.removeListener('message', listener); + } + process.addListener('message', listener); + `, + ], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + serialization: 'advanced', + }, + ); + + return new Promise(resolve => { + child.addListener('message', resolve); + child.send(value); + }); +} + +class MockIpcClient implements Pick { + #data = new Map(); + + async request(method: string, body: any): Promise { + if (method === 'DevDataStore.save') { + this.#data.set(body.key, body.data); + return { saved: true }; + } else if (method === 'DevDataStore.load') { + if (!this.#data.has(body.key)) { + return { loaded: false, data: undefined }; + } + const data = this.#data.get(body.key)!; + return { loaded: true, data: await applyIpcTransform(data) }; + } + throw new Error('Unknown message'); + } +} + +describe('DevDataStore', () => { + it('should save and load data', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect(store.save('test', { foo: 'bar' })).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: { foo: 'bar' }, + }); + }); + + it('should save and load buffers', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', Buffer.from('abc', 'ascii')), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: Buffer.from('abc', 'ascii'), + }); + }); + + it('should save and load array buffers', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', new Uint8Array(Buffer.from('abc', 'ascii'))), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: new Uint8Array(Buffer.from('abc', 'ascii')), + }); + }); + + it('should save and load buffers nested in objects', async () => { + const store = DevDataStore.forTest(new MockIpcClient()); + + await expect( + store.save('test', { + x: Buffer.from('x', 'ascii'), + y: [Buffer.from('y', 'ascii')], + }), + ).resolves.toEqual({ + saved: true, + }); + await expect(store.load('test')).resolves.toEqual({ + loaded: true, + data: { x: Buffer.from('x', 'ascii'), y: [Buffer.from('y', 'ascii')] }, + }); + }); +}); diff --git a/packages/backend-dev-utils/src/DevDataStore.ts b/packages/backend-dev-utils/src/DevDataStore.ts new file mode 100644 index 0000000000..4069ab1bdb --- /dev/null +++ b/packages/backend-dev-utils/src/DevDataStore.ts @@ -0,0 +1,99 @@ +/* + * Copyright 2023 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 { BackstageIpcClient, ipcClient } from './ipcClient'; + +interface SaveRequest { + key: string; + data: unknown; +} + +interface SaveResponse { + saved: boolean; +} + +interface LoadRequest { + key: string; +} + +interface LoadResponse { + loaded: boolean; + data: unknown; +} + +/** + * A data store that can be used to store temporary data during development. + * + * @public + */ +export class DevDataStore { + static #instance?: DevDataStore; + + /** + * Tries to acquire a DevDataStore instance. This will only succeed when the backend + * process is being run through the `@backstage/cli` in development mode. + * + * @returns A DevDataStore instance, or undefined if not available. + */ + static get(): DevDataStore | undefined { + if (ipcClient) { + if (!this.#instance) { + this.#instance = new DevDataStore(ipcClient); + } + return this.#instance; + } + return undefined; + } + + /** @internal */ + static forTest(client: Pick): DevDataStore { + return new DevDataStore(client as BackstageIpcClient); + } + + #client: BackstageIpcClient; + + private constructor(client: BackstageIpcClient) { + this.#client = client; + } + + /** + * Save data to the data store. + * + * @param key - The key used to identify the data. + * @param data - The data to save. The data will be serialized using advanced IPC serialization. + * @returns A promise that resolves to a result object that indicates whether the data was saved. + */ + async save(key: string, data: T): Promise<{ saved: boolean }> { + return this.#client.request( + 'DevDataStore.save', + { key, data }, + ); + } + + /** + * Loads data from the data store. + * + * @param key - The key used to identify the data. + * @returns A promise that resolves to a result object that indicates whether the data was loaded, as well as the data. + */ + async load(key: string): Promise<{ loaded: boolean; data: T }> { + const result = await this.#client.request( + 'DevDataStore.load', + { key }, + ); + return result as { loaded: boolean; data: T }; + } +} diff --git a/packages/backend-dev-utils/src/index.ts b/packages/backend-dev-utils/src/index.ts new file mode 100644 index 0000000000..9b707db029 --- /dev/null +++ b/packages/backend-dev-utils/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2023 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. + */ + +/** + * Local development helpers for backend. + * + * @packageDocumentation + */ + +export { DevDataStore } from './DevDataStore'; diff --git a/packages/backend-dev-utils/src/ipcClient.ts b/packages/backend-dev-utils/src/ipcClient.ts new file mode 100644 index 0000000000..87c1596a39 --- /dev/null +++ b/packages/backend-dev-utils/src/ipcClient.ts @@ -0,0 +1,123 @@ +/* + * Copyright 2023 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. + */ + +type SendMessage = Exclude; + +interface Request { + id: number; + method: string; + body: unknown; + type: string; +} + +type Response = + | { + type: string; + id: number; + body: unknown; + } + | { + type: string; + id: number; + error: Error; + }; + +const requestType = '@backstage/cli/channel/request'; +const responseType = '@backstage/cli/channel/response'; + +/** + * The client side of an IPC communication channel. + * + * @internal + */ +export class BackstageIpcClient { + #messageId = 0; + #sendMessage: SendMessage; + + /** + * Creates a new client if we're in a child process with IPC and BACKSTAGE_CLI_CHANNEL is set. + */ + static create(): BackstageIpcClient | undefined { + const sendMessage = process.send?.bind(process); + return sendMessage && process.env.BACKSTAGE_CLI_CHANNEL + ? new BackstageIpcClient(sendMessage) + : undefined; + } + + constructor(sendMessage: SendMessage) { + this.#sendMessage = sendMessage; + } + + /** + * Send a request to the parent process and wait for a response. + */ + async request( + method: string, + body: TRequestBody, + ): Promise { + return new Promise((resolve, reject) => { + const id = this.#messageId++; + + const request: Request = { + type: requestType, + id, + method, + body, + }; + + this.#sendMessage(request, (e: Error) => { + if (e) { + reject(e); + return; + } + + let timeout: NodeJS.Timeout | undefined = undefined; + + const messageHandler = (response: Response) => { + if (response?.type !== responseType) { + return; + } + if (response.id !== id) { + return; + } + + if ('error' in response) { + const error = new Error(response.error.message); + if (response.error.name) { + error.name = response.error.name; + } + reject(error); + } else { + resolve(response.body as TResponseBody); + } + + clearTimeout(timeout); + process.removeListener('message', messageHandler); + }; + + timeout = setTimeout(() => { + reject(new Error(`IPC request '${method}' with ID ${id} timed out`)); + process.removeListener('message', messageHandler); + }, 5000); + timeout.unref(); + + process.addListener('message', messageHandler as () => void); + }); + }); + } +} + +export const ipcClient = BackstageIpcClient.create(); diff --git a/packages/backend-dev-utils/src/setupTests.ts b/packages/backend-dev-utils/src/setupTests.ts new file mode 100644 index 0000000000..4b9026cde5 --- /dev/null +++ b/packages/backend-dev-utils/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index db0f44fcb2..9e8f7a2d83 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,25 @@ # example-backend-next +## 0.0.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/backend-defaults@0.1.7-next.2 + +## 0.0.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/backend-defaults@0.1.7-next.1 + - @backstage/plugin-app-backend@0.3.42-next.1 + ## 0.0.8-next.0 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 29aad2b6b3..8f007dc7ea 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.8-next.0", + "version": "0.0.8-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -18,7 +18,7 @@ "backstage" ], "scripts": { - "start": "backstage-cli package start", + "start": "EXPERIMENTAL_BACKEND_START=1 backstage-cli package start", "build": "backstage-cli package build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index cbdd69cd40..f5aa2dd9fc 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/backend-plugin-api +## 0.4.0-next.2 + +### Minor Changes + +- e716946103: **BREAKING**: Split out the hook for both lifecycle services so that the first parameter of `addShutdownHook` is the hook function, and the second is the options. +- 0ff03319be: **BREAKING**: The plugin ID option passed to `createBackendPlugin` is now `pluginId`, rather than just `id`. This is to make it match `createBackendModule` more closely. +- 71a5ec0f06: **BREAKING**: Switched out `LogMeta` type for `JsonObject`. +- 610d65e143: Switched `BackendFeature` to be an opaque type. + +### Patch Changes + +- 9c9456fd33: Removed the unused `TypesToServiceRef` type +- 181c03edb5: Aligned opaque type markers to all use a `$type` property with namespacing. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + +## 0.3.2-next.1 + +### Patch Changes + +- ae88f61e00: The `register` methods passed to `createBackendPlugin` and `createBackendModule` + now have dedicated `BackendPluginRegistrationPoints` and + `BackendModuleRegistrationPoints` arguments, respectively. This lets us make it + clear on a type level that it's not possible to pass in extension points as + dependencies to plugins (should only ever be done for modules). This has no + practical effect on code that was already well behaved. +- Updated dependencies + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.3.2-next.0 ### Patch Changes diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md index a7700d81ac..5e64502b78 100644 --- a/packages/backend-plugin-api/api-report.md +++ b/packages/backend-plugin-api/api-report.md @@ -8,6 +8,7 @@ import { Config } from '@backstage/config'; import { Handler } from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; +import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; @@ -17,9 +18,7 @@ import { Readable } from 'stream'; // @public (undocumented) export interface BackendFeature { // (undocumented) - id: string; - // (undocumented) - register(reg: BackendRegistrationPoints): void; + $$type: '@backstage/BackendFeature'; } // @public @@ -47,7 +46,7 @@ export interface BackendModuleRegistrationPoints { // @public export interface BackendPluginConfig { - id: string; + pluginId: string; // (undocumented) register(reg: BackendPluginRegistrationPoints): void; } @@ -73,51 +72,27 @@ export interface BackendPluginRegistrationPoints { } // @public -export interface BackendRegistrationPoints { - // (undocumented) - registerExtensionPoint( - ref: ExtensionPoint, - impl: TExtensionPoint, - ): void; - // (undocumented) - registerInit< - Deps extends { - [name in string]: unknown; - }, - >(options: { - deps: { - [name in keyof Deps]: ServiceRef | ExtensionPoint; - }; - init(deps: Deps): Promise; - }): void; -} - -// @public -export interface CacheClient { +export interface CacheService { delete(key: string): Promise; - get(key: string): Promise; + get(key: string): Promise; set( key: string, value: JsonValue, - options?: CacheClientSetOptions, + options?: CacheServiceSetOptions, ): Promise; + withOptions(options: CacheServiceOptions): CacheService; } // @public -export type CacheClientOptions = { +export type CacheServiceOptions = { defaultTtl?: number; }; // @public -export type CacheClientSetOptions = { +export type CacheServiceSetOptions = { ttl?: number; }; -// @public -export interface CacheService { - getClient: (options?: CacheClientOptions) => CacheClient; -} - // @public (undocumented) export interface ConfigService extends Config {} @@ -166,7 +141,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: RootServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; // @public export function createServiceFactory< @@ -178,7 +153,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options?: TOpts) => RootServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -190,7 +165,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -203,7 +178,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: PluginServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; // @public export function createServiceFactory< @@ -218,7 +193,7 @@ export function createServiceFactory< config: ( options?: TOpts, ) => PluginServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; // @public export function createServiceFactory< @@ -235,7 +210,7 @@ export function createServiceFactory< | (( options: TOpts, ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; // @public export function createServiceRef( @@ -275,7 +250,7 @@ export type ExtensionPoint = { id: string; T: T; toString(): string; - $$ref: 'extension-point'; + $$type: '@backstage/ExtensionPoint'; }; // @public @@ -294,34 +269,34 @@ export interface IdentityService extends IdentityApi {} // @public (undocumented) export interface LifecycleService { - addShutdownHook(options: LifecycleServiceShutdownHook): void; + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void; } // @public (undocumented) -export type LifecycleServiceShutdownHook = { - fn: () => void | Promise; +export type LifecycleServiceShutdownHook = () => void | Promise; + +// @public (undocumented) +export interface LifecycleServiceShutdownOptions { logger?: LoggerService; -}; +} // @public export interface LoggerService { // (undocumented) - child(meta: LogMeta): LoggerService; + child(meta: JsonObject): LoggerService; // (undocumented) - debug(message: string, meta?: Error | LogMeta): void; + debug(message: string, meta?: Error | JsonObject): void; // (undocumented) - error(message: string, meta?: Error | LogMeta): void; + error(message: string, meta?: Error | JsonObject): void; // (undocumented) - info(message: string, meta?: Error | LogMeta): void; + info(message: string, meta?: Error | JsonObject): void; // (undocumented) - warn(message: string, meta?: Error | LogMeta): void; + warn(message: string, meta?: Error | JsonObject): void; } -// @public (undocumented) -export type LogMeta = { - [name: string]: unknown; -}; - // @public (undocumented) export interface PermissionsService extends PermissionEvaluator {} @@ -448,38 +423,18 @@ export type SearchResponseFile = { }; // @public (undocumented) -export type ServiceFactory = - | { - scope: 'root'; - service: ServiceRef; - deps: { - [key in string]: ServiceRef; - }; - factory(deps: { - [key in string]: unknown; - }): Promise; - } - | { - scope: 'plugin'; - service: ServiceRef; - deps: { - [key in string]: ServiceRef; - }; - createRootContext?(deps: { - [key in string]: unknown; - }): Promise; - factory( - deps: { - [key in string]: unknown; - }, - context: unknown, - ): Promise; - }; +export interface ServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> { + // (undocumented) + $$type: '@backstage/ServiceFactory'; + // (undocumented) + service: ServiceRef; +} // @public -export type ServiceFactoryOrFunction = - | ServiceFactory - | (() => ServiceFactory); +export type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory); // @public export type ServiceRef< @@ -490,7 +445,7 @@ export type ServiceRef< scope: TScope; T: TService; toString(): string; - $$ref: 'service'; + $$type: '@backstage/ServiceRef'; }; // @public (undocumented) @@ -498,7 +453,7 @@ export interface ServiceRefConfig { // (undocumented) defaultFactory?: ( service: ServiceRef, - ) => Promise>; + ) => Promise; // (undocumented) id: string; // (undocumented) @@ -508,7 +463,7 @@ export interface ServiceRefConfig { // @public export interface SharedBackendEnvironment { // (undocumented) - $$type: 'SharedBackendEnvironment'; + $$type: '@backstage/SharedBackendEnvironment'; } // @public @@ -525,11 +480,6 @@ export interface TokenManagerService { }>; } -// @public (undocumented) -export type TypesToServiceRef = { - [key in keyof T]: ServiceRef; -}; - // @public export interface UrlReaderService { readTree(url: string, options?: ReadTreeOptions): Promise; diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 41164e7870..7243f3485c 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.3.2-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-plugin-api/src/services/definitions/CacheService.ts b/packages/backend-plugin-api/src/services/definitions/CacheService.ts index 2702fdac6d..ccf88823b0 100644 --- a/packages/backend-plugin-api/src/services/definitions/CacheService.ts +++ b/packages/backend-plugin-api/src/services/definitions/CacheService.ts @@ -17,29 +17,11 @@ import { JsonValue } from '@backstage/types'; /** - * Manages access to cache stores that plugins get. + * Options passed to {@link CacheService.set}. * * @public */ -export interface CacheService { - /** - * Provides backend plugins cache connections for themselves. - * - * @remarks - * - * The purpose of this method is to allow plugins to get isolated data stores - * so that plugins are discouraged from cache-level integration and/or cache - * key collisions. - */ - getClient: (options?: CacheClientOptions) => CacheClient; -} - -/** - * Options passed to {@link CacheClient.set}. - * - * @public - */ -export type CacheClientSetOptions = { +export type CacheServiceSetOptions = { /** * Optional TTL in milliseconds. Defaults to the TTL provided when the client * was set up (or no TTL if none are provided). @@ -48,17 +30,31 @@ export type CacheClientSetOptions = { }; /** - * A pre-configured, storage agnostic cache client suitable for use by + * Options passed to {@link CacheService.withOptions}. + * + * @public + */ +export type CacheServiceOptions = { + /** + * An optional default TTL (in milliseconds) to be set when getting a client + * instance. If not provided, data will persist indefinitely by default (or + * can be configured per entry at set-time). + */ + defaultTtl?: number; +}; + +/** + * A pre-configured, storage agnostic cache service suitable for use by * Backstage plugins. * * @public */ -export interface CacheClient { +export interface CacheService { /** * Reads data from a cache store for the given key. If no data was found, * returns undefined. */ - get(key: string): Promise; + get(key: string): Promise; /** * Writes the given data to a cache store, associated with the given key. An @@ -68,25 +64,16 @@ export interface CacheClient { set( key: string, value: JsonValue, - options?: CacheClientSetOptions, + options?: CacheServiceSetOptions, ): Promise; /** * Removes the given key from the cache store. */ delete(key: string): Promise; -} -/** - * Options given when constructing a {@link CacheClient}. - * - * @public - */ -export type CacheClientOptions = { /** - * An optional default TTL (in milliseconds) to be set when getting a client - * instance. If not provided, data will persist indefinitely by default (or - * can be configured per entry at set-time). + * Creates a new {@link CacheService} instance with the given options. */ - defaultTtl?: number; -}; + withOptions(options: CacheServiceOptions): CacheService; +} diff --git a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts index 25cc47270e..89351194e6 100644 --- a/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LifecycleService.ts @@ -18,22 +18,28 @@ import { LoggerService } from './LoggerService'; /** * @public - **/ -export type LifecycleServiceShutdownHook = { - fn: () => void | Promise; + */ +export type LifecycleServiceShutdownHook = () => void | Promise; +/** + * @public + */ +export interface LifecycleServiceShutdownOptions { /** * Optional {@link LoggerService} that will be used for logging instead of the default logger. */ logger?: LoggerService; -}; +} /** * @public - **/ + */ export interface LifecycleService { /** * Register a function to be called when the backend is shutting down. */ - addShutdownHook(options: LifecycleServiceShutdownHook): void; + addShutdownHook( + hook: LifecycleServiceShutdownHook, + options?: LifecycleServiceShutdownOptions, + ): void; } diff --git a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts index 269dfa0166..2e4edc60be 100644 --- a/packages/backend-plugin-api/src/services/definitions/LoggerService.ts +++ b/packages/backend-plugin-api/src/services/definitions/LoggerService.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -/** - * @public - */ -export type LogMeta = { [name: string]: unknown }; +import { JsonObject } from '@backstage/types'; /** * A service that provides a logging facility. @@ -25,10 +22,10 @@ export type LogMeta = { [name: string]: unknown }; * @public */ export interface LoggerService { - error(message: string, meta?: Error | LogMeta): void; - warn(message: string, meta?: Error | LogMeta): void; - info(message: string, meta?: Error | LogMeta): void; - debug(message: string, meta?: Error | LogMeta): void; + error(message: string, meta?: Error | JsonObject): void; + warn(message: string, meta?: Error | JsonObject): void; + info(message: string, meta?: Error | JsonObject): void; + debug(message: string, meta?: Error | JsonObject): void; - child(meta: LogMeta): LoggerService; + child(meta: JsonObject): LoggerService; } diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index c5af0967bd..0122bc0be8 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -17,9 +17,8 @@ export { coreServices } from './coreServices'; export type { CacheService, - CacheClient, - CacheClientOptions, - CacheClientSetOptions, + CacheServiceOptions, + CacheServiceSetOptions, } from './CacheService'; export type { ConfigService } from './ConfigService'; export type { DatabaseService } from './DatabaseService'; @@ -28,8 +27,9 @@ export type { HttpRouterService } from './HttpRouterService'; export type { LifecycleService, LifecycleServiceShutdownHook, + LifecycleServiceShutdownOptions, } from './LifecycleService'; -export type { LoggerService, LogMeta } from './LoggerService'; +export type { LoggerService } from './LoggerService'; export type { PermissionsService } from './PermissionsService'; export type { PluginMetadataService } from './PluginMetadataService'; export type { RootHttpRouterService } from './RootHttpRouterService'; diff --git a/packages/backend-plugin-api/src/services/system/index.ts b/packages/backend-plugin-api/src/services/system/index.ts index 74be9f8b11..2b91758cbc 100644 --- a/packages/backend-plugin-api/src/services/system/index.ts +++ b/packages/backend-plugin-api/src/services/system/index.ts @@ -17,7 +17,6 @@ export type { ServiceRef, ServiceRefConfig, - TypesToServiceRef, ServiceFactory, PluginServiceFactoryConfig, RootServiceFactoryConfig, diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index 2615c5e3a3..190ef7c13e 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -44,41 +44,39 @@ export type ServiceRef< toString(): string; - $$ref: 'service'; + $$type: '@backstage/ServiceRef'; }; /** @public */ -export type TypesToServiceRef = { [key in keyof T]: ServiceRef }; +export interface ServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> { + $$type: '@backstage/ServiceFactory'; -/** @public */ -export type ServiceFactory = - | { - // This scope prop is needed in addition to the service ref, as TypeScript - // can't properly discriminate the two factory types otherwise. - scope: 'root'; - service: ServiceRef; - deps: { [key in string]: ServiceRef }; - factory(deps: { [key in string]: unknown }): Promise; - } - | { - scope: 'plugin'; - service: ServiceRef; - deps: { [key in string]: ServiceRef }; - createRootContext?(deps: { [key in string]: unknown }): Promise; - factory( - deps: { [key in string]: unknown }, - context: unknown, - ): Promise; - }; + service: ServiceRef; +} + +/** @internal */ +export interface InternalServiceFactory< + TService = unknown, + TScope extends 'plugin' | 'root' = 'plugin' | 'root', +> extends ServiceFactory { + version: 'v1'; + deps: { [key in string]: ServiceRef }; + createRootContext?(deps: { [key in string]: unknown }): Promise; + factory( + deps: { [key in string]: unknown }, + context: unknown, + ): Promise; +} /** * Represents either a {@link ServiceFactory} or a function that returns one. * * @public */ -export type ServiceFactoryOrFunction = - | ServiceFactory - | (() => ServiceFactory); +export type ServiceFactoryOrFunction = ServiceFactory | (() => ServiceFactory); /** @public */ export interface ServiceRefConfig { @@ -86,7 +84,7 @@ export interface ServiceRefConfig { scope?: TScope; defaultFactory?: ( service: ServiceRef, - ) => Promise>; + ) => Promise; } /** @@ -119,7 +117,7 @@ export function createServiceRef( toString() { return `serviceRef{${config.id}}`; }, - $$ref: 'service', // TODO: declare + $$type: '@backstage/ServiceRef', __defaultFactory: defaultFactory, } as ServiceRef & { __defaultFactory?: ( @@ -178,7 +176,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: RootServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; /** * Creates a root scoped service factory with optional options. * @@ -192,7 +190,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options?: TOpts) => RootServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; /** * Creates a root scoped service factory with required options. * @@ -206,7 +204,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: (options: TOpts) => RootServiceFactoryConfig, -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; /** * Creates a plugin scoped service factory without options. * @@ -221,7 +219,7 @@ export function createServiceFactory< TOpts extends object | undefined = undefined, >( config: PluginServiceFactoryConfig, -): () => ServiceFactory; +): () => ServiceFactory; /** * Creates a plugin scoped service factory with optional options. * @@ -238,7 +236,7 @@ export function createServiceFactory< config: ( options?: TOpts, ) => PluginServiceFactoryConfig, -): (options?: TOpts) => ServiceFactory; +): (options?: TOpts) => ServiceFactory; /** * Creates a plugin scoped service factory with required options. * @@ -257,7 +255,7 @@ export function createServiceFactory< | (( options: TOpts, ) => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory; +): (options: TOpts) => ServiceFactory; export function createServiceFactory< TService, TImpl extends TService, @@ -274,20 +272,40 @@ export function createServiceFactory< ) => PluginServiceFactoryConfig) | (() => RootServiceFactoryConfig) | (() => PluginServiceFactoryConfig), -): (options: TOpts) => ServiceFactory { +): (options: TOpts) => ServiceFactory { const configCallback = typeof config === 'function' ? config : () => config; - return (options: TOpts) => { - const c = configCallback(options); + return ( + options: TOpts, + ): InternalServiceFactory => { + const anyConf = configCallback(options); + if (anyConf.service.scope === 'root') { + const c = anyConf as RootServiceFactoryConfig; + return { + $$type: '@backstage/ServiceFactory', + version: 'v1', + service: c.service, + deps: c.deps, + factory: async (deps: TDeps) => c.factory(deps), + }; + } + const c = anyConf as PluginServiceFactoryConfig< + TService, + TContext, + TImpl, + TDeps + >; return { - ...c, + $$type: '@backstage/ServiceFactory', + version: 'v1', + service: c.service, ...('createRootContext' in c ? { createRootContext: async (deps: TDeps) => c?.createRootContext?.(deps), } : {}), + deps: c.deps, factory: async (deps: TDeps, ctx: TContext) => c.factory(deps, ctx), - scope: c.service.scope, - } as ServiceFactory; + }; }; } diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts index ec2cf1fe49..381a4799d2 100644 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts +++ b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.test.ts @@ -48,7 +48,7 @@ describe('createSharedEnvironment', () => { expect(env).toBeDefined(); const internalEnv = env() as unknown as InternalSharedBackendEnvironment; expect(internalEnv).toEqual({ - $$type: 'SharedBackendEnvironment', + $$type: '@backstage/SharedBackendEnvironment', version: 'v1', services: undefined, }); diff --git a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts index 2eb2cdec6a..57f0533523 100644 --- a/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts +++ b/packages/backend-plugin-api/src/wiring/createSharedEnvironment.ts @@ -31,7 +31,7 @@ export interface SharedBackendEnvironmentConfig { * @public */ export interface SharedBackendEnvironment { - $$type: 'SharedBackendEnvironment'; + $$type: '@backstage/SharedBackendEnvironment'; // NOTE: This type is opaque in order to allow for future API evolution without // cluttering the external API. For example we might want to add support @@ -93,7 +93,7 @@ export function createSharedEnvironment< // Here to ensure type safety in this internal implementation. const env: SharedBackendEnvironment & InternalSharedBackendEnvironment = { - $$type: 'SharedBackendEnvironment', + $$type: '@backstage/SharedBackendEnvironment', version: 'v1', services, }; diff --git a/packages/backend-plugin-api/src/wiring/factories.test.ts b/packages/backend-plugin-api/src/wiring/factories.test.ts index dbdf0ead14..ae199d84e4 100644 --- a/packages/backend-plugin-api/src/wiring/factories.test.ts +++ b/packages/backend-plugin-api/src/wiring/factories.test.ts @@ -19,6 +19,7 @@ import { createBackendPlugin, createExtensionPoint, } from './factories'; +import { InternalBackendFeature } from './types'; describe('createExtensionPoint', () => { it('should create an ExtensionPoint', () => { @@ -33,12 +34,31 @@ describe('createExtensionPoint', () => { describe('createBackendPlugin', () => { it('should create a BackendPlugin', () => { const plugin = createBackendPlugin((_options: { a: string }) => ({ - id: 'x', - register() {}, + pluginId: 'x', + register(r) { + r.registerInit({ deps: {}, async init() {} }); + }, })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' }).id).toBe('x'); + expect(plugin({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); + expect( + (plugin({ a: 'a' }) as InternalBackendFeature).getRegistrations(), + ).toEqual([ + { + type: 'plugin', + pluginId: 'x', + extensionPoints: [], + init: { + deps: expect.any(Object), + func: expect.any(Function), + }, + }, + ]); // @ts-expect-error expect(plugin()).toBeDefined(); // @ts-expect-error @@ -47,7 +67,7 @@ describe('createBackendPlugin', () => { it('should create plugins with optional options', () => { const plugin = createBackendPlugin((_options?: { a: string }) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); @@ -59,7 +79,7 @@ describe('createBackendPlugin', () => { it('should create plugins without options', () => { const plugin = createBackendPlugin({ - id: 'x', + pluginId: 'x', register() {}, }); expect(plugin).toBeDefined(); @@ -74,12 +94,16 @@ describe('createBackendPlugin', () => { a: string; } const plugin = createBackendPlugin((_options: TestOptions) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); expect(plugin({ a: 'a' })).toBeDefined(); - expect(plugin({ a: 'a' }).id).toBe('x'); + expect(plugin({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); // @ts-expect-error expect(plugin()).toBeDefined(); // @ts-expect-error @@ -91,7 +115,7 @@ describe('createBackendPlugin', () => { a: string; } const plugin = createBackendPlugin((_options?: TestOptions) => ({ - id: 'x', + pluginId: 'x', register() {}, })); expect(plugin).toBeDefined(); @@ -107,11 +131,30 @@ describe('createBackendModule', () => { const mod = createBackendModule((_options: { a: string }) => ({ pluginId: 'x', moduleId: 'y', - register() {}, + register(r) { + r.registerInit({ deps: {}, async init() {} }); + }, })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' }).id).toBe('x.y'); + expect(mod({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); + expect( + (mod({ a: 'a' }) as InternalBackendFeature).getRegistrations(), + ).toEqual([ + { + type: 'module', + pluginId: 'x', + moduleId: 'y', + init: { + deps: expect.any(Object), + func: expect.any(Function), + }, + }, + ]); // @ts-expect-error expect(mod()).toBeDefined(); // @ts-expect-error @@ -155,7 +198,11 @@ describe('createBackendModule', () => { })); expect(mod).toBeDefined(); expect(mod({ a: 'a' })).toBeDefined(); - expect(mod({ a: 'a' }).id).toBe('x.y'); + expect(mod({ a: 'a' })).toEqual({ + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations: expect.any(Function), + }); // @ts-expect-error expect(mod()).toBeDefined(); // @ts-expect-error diff --git a/packages/backend-plugin-api/src/wiring/factories.ts b/packages/backend-plugin-api/src/wiring/factories.ts index d281335a8e..928c933af0 100644 --- a/packages/backend-plugin-api/src/wiring/factories.ts +++ b/packages/backend-plugin-api/src/wiring/factories.ts @@ -17,9 +17,11 @@ import { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendRegistrationPoints, BackendFeature, ExtensionPoint, + InternalBackendFeature, + InternalBackendModuleRegistration, + InternalBackendPluginRegistration, } from './types'; /** @@ -55,7 +57,7 @@ export function createExtensionPoint( toString() { return `extensionPoint{${config.id}}`; }, - $$ref: 'extension-point', // TODO: declare + $$type: '@backstage/ExtensionPoint', }; } @@ -72,7 +74,7 @@ export interface BackendPluginConfig { * * @see {@link https://backstage.io/docs/backend-system/architecture/naming-patterns | Recommended naming patterns} */ - id: string; + pluginId: string; register(reg: BackendPluginRegistrationPoints): void; } @@ -86,11 +88,62 @@ export interface BackendPluginConfig { export function createBackendPlugin( config: BackendPluginConfig | ((...params: TOptions) => BackendPluginConfig), ): (...params: TOptions) => BackendFeature { - if (typeof config === 'function') { - return config; - } + const configCallback = typeof config === 'function' ? config : () => config; + return (...options: TOptions): InternalBackendFeature => { + const c = configCallback(...options); - return () => config; + let registrations: InternalBackendPluginRegistration[]; + + return { + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations() { + if (registrations) { + return registrations; + } + const extensionPoints: InternalBackendPluginRegistration['extensionPoints'] = + []; + let init: InternalBackendPluginRegistration['init'] | undefined = + undefined; + + c.register({ + registerExtensionPoint(ext, impl) { + if (init) { + throw new Error( + 'registerExtensionPoint called after registerInit', + ); + } + extensionPoints.push([ext, impl]); + }, + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); + + if (!init) { + throw new Error( + `registerInit was not called by register in ${c.pluginId}`, + ); + } + + registrations = [ + { + type: 'plugin', + pluginId: c.pluginId, + extensionPoints, + init, + }, + ]; + return registrations; + }, + }; + }; } /** @@ -124,21 +177,50 @@ export interface BackendModuleConfig { export function createBackendModule( config: BackendModuleConfig | ((...params: TOptions) => BackendModuleConfig), ): (...params: TOptions) => BackendFeature { - if (typeof config === 'function') { - return (...options: TOptions) => { - const c = config(...options); - return { - id: `${c.pluginId}.${c.moduleId}`, - register: c.register, - }; + const configCallback = typeof config === 'function' ? config : () => config; + return (...options: TOptions): InternalBackendFeature => { + const c = configCallback(...options); + + let registrations: InternalBackendModuleRegistration[]; + + return { + $$type: '@backstage/BackendFeature', + version: 'v1', + getRegistrations() { + if (registrations) { + return registrations; + } + let init: InternalBackendModuleRegistration['init'] | undefined = + undefined; + + c.register({ + registerInit(regInit) { + if (init) { + throw new Error('registerInit must only be called once'); + } + init = { + deps: regInit.deps, + func: regInit.init, + }; + }, + }); + + if (!init) { + throw new Error( + `registerInit was not called by register in ${c.moduleId} module for ${c.pluginId}`, + ); + } + + registrations = [ + { + type: 'module', + pluginId: c.pluginId, + moduleId: c.moduleId, + init, + }, + ]; + return registrations; + }, }; - } - return () => ({ - id: `${config.pluginId}.${config.moduleId}`, - register(register: BackendRegistrationPoints) { - return config.register({ - registerInit: register.registerInit.bind(register), - }); - }, - }); + }; } diff --git a/packages/backend-plugin-api/src/wiring/index.ts b/packages/backend-plugin-api/src/wiring/index.ts index e0c25eeb4e..242301ea4d 100644 --- a/packages/backend-plugin-api/src/wiring/index.ts +++ b/packages/backend-plugin-api/src/wiring/index.ts @@ -32,7 +32,6 @@ export { export type { BackendModuleRegistrationPoints, BackendPluginRegistrationPoints, - BackendRegistrationPoints, BackendFeature, ExtensionPoint, } from './types'; diff --git a/packages/backend-plugin-api/src/wiring/types.ts b/packages/backend-plugin-api/src/wiring/types.ts index 6e081f57e5..c81ee3ceb7 100644 --- a/packages/backend-plugin-api/src/wiring/types.ts +++ b/packages/backend-plugin-api/src/wiring/types.ts @@ -32,29 +32,9 @@ export type ExtensionPoint = { toString(): string; - $$ref: 'extension-point'; + $$type: '@backstage/ExtensionPoint'; }; -/** - * The callbacks passed to the `register` method of a backend feature; this is - * essentially a superset of {@link BackendPluginRegistrationPoints} and - * {@link BackendModuleRegistrationPoints}. - * - * @public - */ -export interface BackendRegistrationPoints { - registerExtensionPoint( - ref: ExtensionPoint, - impl: TExtensionPoint, - ): void; - registerInit(options: { - deps: { - [name in keyof Deps]: ServiceRef | ExtensionPoint; - }; - init(deps: Deps): Promise; - }): void; -} - /** * The callbacks passed to the `register` method of a backend plugin. * @@ -89,7 +69,36 @@ export interface BackendModuleRegistrationPoints { /** @public */ export interface BackendFeature { - // TODO(Rugvip): Try to get rid of the ID at this level, allowing for a feature to register multiple features as a bundle - id: string; - register(reg: BackendRegistrationPoints): void; + // NOTE: This type is opaque in order to simplify future API evolution. + $$type: '@backstage/BackendFeature'; +} + +/** @internal */ +export interface InternalBackendFeature extends BackendFeature { + version: 'v1'; + getRegistrations(): Array< + InternalBackendPluginRegistration | InternalBackendModuleRegistration + >; +} + +/** @internal */ +export interface InternalBackendPluginRegistration { + pluginId: string; + type: 'plugin'; + extensionPoints: Array, unknown]>; + init: { + deps: Record>; + func(deps: Record): Promise; + }; +} + +/** @internal */ +export interface InternalBackendModuleRegistration { + pluginId: string; + moduleId: string; + type: 'module'; + init: { + deps: Record | ExtensionPoint>; + func(deps: Record): Promise; + }; } diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index a6a8b85616..1e32f34978 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/backend-tasks +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## 0.4.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.4.3-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index e63077c1e6..ee7d7d6e67 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.4.3-next.0", + "version": "0.4.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 47d6023d62..bf7b6c6713 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/backend-test-utils +## 0.1.34-next.2 + +### Patch Changes + +- baf6e4c96a: Removed unnecessary `@backstage/cli` dependency. +- 1835311713: Added explicit return type signature for `mockServices.config()`. +- e716946103: Updated usage of the lifecycle service. +- 7e7557a2be: Updated the `mockServices.rootLogger` options to accept a single level option instead. +- 610d65e143: Updates to match new `BackendFeature` type. +- e412d33025: Use the new `*ServiceFactory` exports from `@backstage/backend-app-api` +- f1adb2e36b: Removed the `ref` from all `mockServices`. +- 71a5ec0f06: Updated usages of `LogMeta`. +- Updated dependencies + - @backstage/backend-app-api@0.4.0-next.2 + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## 0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-app-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 0.1.34-next.0 ### Patch Changes diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index 232f7e8136..0b3d7dd843 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -6,7 +6,6 @@ import { Backend } from '@backstage/backend-app-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; import { CacheService } from '@backstage/backend-plugin-api'; -import { ConfigReader } from '@backstage/config'; import { ConfigService } from '@backstage/backend-plugin-api'; import { DatabaseService } from '@backstage/backend-plugin-api'; import { ExtendedHttpServer } from '@backstage/backend-app-api'; @@ -20,7 +19,6 @@ import { LifecycleService } from '@backstage/backend-plugin-api'; import { LoggerService } from '@backstage/backend-plugin-api'; import { PermissionsService } from '@backstage/backend-plugin-api'; import { RootLifecycleService } from '@backstage/backend-plugin-api'; -import { RootLoggerService } from '@backstage/backend-plugin-api'; import { SchedulerService } from '@backstage/backend-plugin-api'; import { ServiceFactory } from '@backstage/backend-plugin-api'; import { ServiceRef } from '@backstage/backend-plugin-api'; @@ -35,12 +33,10 @@ export namespace mockServices { // (undocumented) export namespace cache { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) - export function config(options?: config.Options): ConfigReader; + export function config(options?: config.Options): ConfigService; // (undocumented) export namespace config { // (undocumented) @@ -48,62 +44,48 @@ export namespace mockServices { data?: JsonObject; }; const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: (options?: Options | undefined) => ServiceFactory; + factory: ( + options?: Options | undefined, + ) => ServiceFactory; } // (undocumented) export namespace database { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace httpRouter { - const // (undocumented) - ref: ServiceRef; const // (undocumented) factory: ( options?: HttpRouterFactoryOptions | undefined, - ) => ServiceFactory; + ) => ServiceFactory; } // (undocumented) export function identity(): IdentityService; // (undocumented) export namespace identity { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace lifecycle { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace logger { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace permissions { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace rootLifecycle { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export function rootLogger(options?: rootLogger.Options): LoggerService; @@ -111,42 +93,29 @@ export namespace mockServices { export namespace rootLogger { // (undocumented) export type Options = { - levels: - | boolean - | { - error: boolean; - warn: boolean; - info: boolean; - debug: boolean; - }; + level?: 'none' | 'error' | 'warn' | 'info' | 'debug'; }; const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: (options?: Options | undefined) => ServiceFactory; + factory: ( + options?: Options | undefined, + ) => ServiceFactory; } // (undocumented) export namespace scheduler { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export function tokenManager(): TokenManagerService; // (undocumented) export namespace tokenManager { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } // (undocumented) export namespace urlReader { const // (undocumented) - ref: ServiceRef; - const // (undocumented) - factory: () => ServiceFactory; + factory: () => ServiceFactory; } } diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 949cf9d299..08e00e1c5e 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.34-next.0", + "version": "0.1.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -37,7 +37,6 @@ "@backstage/backend-app-api": "workspace:^", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", - "@backstage/cli": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts new file mode 100644 index 0000000000..a3cbb5c384 --- /dev/null +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts @@ -0,0 +1,131 @@ +/* + * Copyright 2023 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 { MockRootLoggerService } from './MockRootLoggerService'; + +describe('MockRootLoggerService', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should be silent by default', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create(); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set none level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'none' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set error level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'error' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set warn level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'warn' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).not.toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set info level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'info' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).toHaveBeenCalled(); + expect(console.debug).not.toHaveBeenCalled(); + }); + + it('shuld be able to set debug level', () => { + jest.spyOn(console, 'error').mockImplementation(() => {}); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.spyOn(console, 'info').mockImplementation(() => {}); + jest.spyOn(console, 'debug').mockImplementation(() => {}); + + const logger = MockRootLoggerService.create({ level: 'debug' }); + logger.error('error'); + logger.warn('warn'); + logger.info('info'); + logger.debug('debug'); + + expect(console.error).toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalled(); + expect(console.info).toHaveBeenCalled(); + expect(console.debug).toHaveBeenCalled(); + }); +}); diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts index 780d330bfb..8b973eeeab 100644 --- a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts +++ b/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts @@ -16,58 +16,65 @@ import { LoggerService, - LogMeta, RootLoggerService, } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; import type { mockServices } from './mockServices'; -export class MockRootLoggerService implements RootLoggerService { - #levels: Exclude; - #meta: LogMeta; +const levels = { + none: 0, + error: 1, + warn: 2, + info: 3, + debug: 4, +}; - error(message: string, meta?: LogMeta | Error | undefined): void { +export class MockRootLoggerService implements RootLoggerService { + #level: number; + #meta: JsonObject; + + static create( + options?: mockServices.rootLogger.Options, + ): MockRootLoggerService { + const level = options?.level ?? 'none'; + if (!(level in levels)) { + throw new Error(`Invalid log level '${level}'`); + } + return new MockRootLoggerService(levels[level], {}); + } + + error(message: string, meta?: JsonObject | Error | undefined): void { this.#log('error', message, meta); } - warn(message: string, meta?: LogMeta | Error | undefined): void { + warn(message: string, meta?: JsonObject | Error | undefined): void { this.#log('warn', message, meta); } - info(message: string, meta?: LogMeta | Error | undefined): void { + info(message: string, meta?: JsonObject | Error | undefined): void { this.#log('info', message, meta); } - debug(message: string, meta?: LogMeta | Error | undefined): void { + debug(message: string, meta?: JsonObject | Error | undefined): void { this.#log('debug', message, meta); } - child(meta: LogMeta): LoggerService { - return new MockRootLoggerService(this.#levels, { ...this.#meta, ...meta }); + child(meta: JsonObject): LoggerService { + return new MockRootLoggerService(this.#level, { ...this.#meta, ...meta }); } - constructor( - levels: mockServices.rootLogger.Options['levels'], - meta: LogMeta, - ) { - if (typeof levels === 'boolean') { - this.#levels = { - error: levels, - debug: levels, - info: levels, - warn: levels, - }; - } else { - this.#levels = levels; - } + private constructor(level: number, meta: JsonObject) { + this.#level = level; this.#meta = meta; } #log( level: 'error' | 'warn' | 'info' | 'debug', message: string, - meta?: LogMeta | Error | undefined, + meta?: JsonObject | Error | undefined, ) { - if (this.#levels[level]) { + const levelValue = levels[level] ?? 0; + if (levelValue <= this.#level) { const labels = Object.entries(this.#meta) .map(([key, value]) => `${key}=${value}`) .join(','); diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts index f86d8bac55..2e97cc63fb 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/next/services/mockServices.ts @@ -15,6 +15,7 @@ */ import { + ConfigService, coreServices, createServiceFactory, IdentityService, @@ -24,60 +25,60 @@ import { TokenManagerService, } from '@backstage/backend-plugin-api'; import { - cacheFactory, - databaseFactory, - httpRouterFactory, - lifecycleFactory, - loggerFactory, - permissionsFactory, - rootLifecycleFactory, - schedulerFactory, - urlReaderFactory, + cacheServiceFactory, + databaseServiceFactory, + httpRouterServiceFactory, + lifecycleServiceFactory, + loggerServiceFactory, + permissionsServiceFactory, + rootLifecycleServiceFactory, + schedulerServiceFactory, + urlReaderServiceFactory, } from '@backstage/backend-app-api'; import { ConfigReader } from '@backstage/config'; import { JsonObject } from '@backstage/types'; import { MockIdentityService } from './MockIdentityService'; import { MockRootLoggerService } from './MockRootLoggerService'; -function simpleFactory( - ref: ServiceRef, +function simpleFactory< + TService, + TScope extends 'root' | 'plugin', + TOptions extends [options?: object] = [], +>( + ref: ServiceRef, factory: (...options: TOptions) => TService, -): (...options: TOptions) => ServiceFactory { +): (...options: TOptions) => ServiceFactory { return createServiceFactory((options: unknown) => ({ service: ref as ServiceRef, deps: {}, async factory() { return (factory as any)(options); }, - })); + })) as (...options: TOptions) => ServiceFactory; } /** * @alpha */ export namespace mockServices { - export function config(options?: config.Options) { + export function config(options?: config.Options): ConfigService { return new ConfigReader(options?.data, 'mock-config'); } export namespace config { export type Options = { data?: JsonObject }; - export const ref = coreServices.config; - export const factory = simpleFactory(ref, config); + export const factory = simpleFactory(coreServices.config, config); } export function rootLogger(options?: rootLogger.Options): LoggerService { - return new MockRootLoggerService(options?.levels ?? false, {}); + return MockRootLoggerService.create(options); } export namespace rootLogger { export type Options = { - levels: - | boolean - | { error: boolean; warn: boolean; info: boolean; debug: boolean }; + level?: 'none' | 'error' | 'warn' | 'info' | 'debug'; }; - export const ref = coreServices.rootLogger; - export const factory = simpleFactory(ref, rootLogger); + export const factory = simpleFactory(coreServices.rootLogger, rootLogger); } export function tokenManager(): TokenManagerService { @@ -93,55 +94,47 @@ export namespace mockServices { }; } export namespace tokenManager { - export const ref = coreServices.tokenManager; - export const factory = simpleFactory(ref, tokenManager); + export const factory = simpleFactory( + coreServices.tokenManager, + tokenManager, + ); } export function identity(): IdentityService { return new MockIdentityService(); } export namespace identity { - export const ref = coreServices.identity; - export const factory = simpleFactory(ref, identity); + export const factory = simpleFactory(coreServices.identity, identity); } // TODO(Rugvip): Not all core services have implementations available here yet. // some may need a bit more refactoring for it to be simpler to // re-implement functioning mock versions here. export namespace cache { - export const ref = coreServices.cache; - export const factory = cacheFactory; + export const factory = cacheServiceFactory; } export namespace database { - export const ref = coreServices.database; - export const factory = databaseFactory; + export const factory = databaseServiceFactory; } export namespace httpRouter { - export const ref = coreServices.httpRouter; - export const factory = httpRouterFactory; + export const factory = httpRouterServiceFactory; } export namespace lifecycle { - export const ref = coreServices.lifecycle; - export const factory = lifecycleFactory; + export const factory = lifecycleServiceFactory; } export namespace logger { - export const ref = coreServices.logger; - export const factory = loggerFactory; + export const factory = loggerServiceFactory; } export namespace permissions { - export const ref = coreServices.permissions; - export const factory = permissionsFactory; + export const factory = permissionsServiceFactory; } export namespace rootLifecycle { - export const ref = coreServices.rootLifecycle; - export const factory = rootLifecycleFactory; + export const factory = rootLifecycleServiceFactory; } export namespace scheduler { - export const ref = coreServices.scheduler; - export const factory = schedulerFactory; + export const factory = schedulerServiceFactory; } export namespace urlReader { - export const ref = coreServices.urlReader; - export const factory = urlReaderFactory; + export const factory = urlReaderServiceFactory; } } diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index dca463a9ae..aa93a7dae1 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -40,10 +40,8 @@ beforeAll(async () => { env.registerInit({ deps: { lifecycle: coreServices.lifecycle }, async init({ lifecycle }) { - lifecycle.addShutdownHook({ - fn() { - globalTestBackendHasBeenStopped = true; - }, + lifecycle.addShutdownHook(() => { + globalTestBackendHasBeenStopped = true; }); }, }); @@ -145,7 +143,7 @@ describe('TestBackend', () => { lifecycle: coreServices.lifecycle, }, async init({ lifecycle }) { - lifecycle.addShutdownHook({ fn: shutdownSpy }); + lifecycle.addShutdownHook(shutdownSpy); }, }); }, @@ -165,7 +163,7 @@ describe('TestBackend', () => { expect.assertions(2); const testPlugin = createBackendPlugin({ - id: 'test', + pluginId: 'test', register(env) { env.registerInit({ deps: { @@ -201,7 +199,7 @@ describe('TestBackend', () => { it('should allow making requests via supertest', async () => { const testPlugin = createBackendPlugin({ - id: 'test', + pluginId: 'test', register(env) { env.registerInit({ deps: { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index db1016fcb6..bbda9854d4 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -30,6 +30,7 @@ import { BackendFeature, ExtensionPoint, coreServices, + createBackendPlugin, } from '@backstage/backend-plugin-api'; import { mockServices } from '../services'; import { ConfigReader } from '@backstage/config'; @@ -129,12 +130,7 @@ export async function startTestBackend< { logger }, ); - lifecycle.addShutdownHook({ - async fn() { - await server.stop(); - }, - logger, - }); + lifecycle.addShutdownHook(() => server.stop(), { logger }); await server.start(); @@ -198,16 +194,18 @@ export async function startTestBackend< backendInstancesToCleanUp.push(backend); - backend.add({ - id: `---test-extension-point-registrar`, - register(reg) { - for (const [ref, impl] of extensionPoints) { - reg.registerExtensionPoint(ref, impl); - } + backend.add( + createBackendPlugin({ + pluginId: `---test-extension-point-registrar`, + register(reg) { + for (const [ref, impl] of extensionPoints) { + reg.registerExtensionPoint(ref, impl); + } - reg.registerInit({ deps: {}, async init() {} }); - }, - }); + reg.registerInit({ deps: {}, async init() {} }); + }, + })(), + ); for (const feature of features) { backend.add(feature); diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index bcff085d0b..7053244da9 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,102 @@ # example-backend +## 0.2.80-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-backend@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/plugin-search-backend@1.2.3-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-events-backend@0.2.3-next.2 + - @backstage/plugin-kafka-backend@0.2.35-next.2 + - @backstage/plugin-proxy-backend@0.2.36-next.2 + - @backstage/plugin-app-backend@0.3.42-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-backend@0.17.5-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/plugin-playlist-backend@0.2.5-next.2 + - @backstage/plugin-rollbar-backend@0.1.39-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.2 + - @backstage/plugin-tech-insights-backend@0.5.8-next.2 + - @backstage/plugin-techdocs-backend@1.5.3-next.2 + - example-app@0.2.80-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.2 + - @backstage/plugin-azure-devops-backend@0.3.21-next.2 + - @backstage/plugin-azure-sites-backend@0.1.4-next.2 + - @backstage/plugin-badges-backend@0.1.36-next.2 + - @backstage/plugin-code-coverage-backend@0.2.8-next.2 + - @backstage/plugin-explore-backend@0.0.4-next.2 + - @backstage/plugin-graphql-backend@0.1.32-next.2 + - @backstage/plugin-jenkins-backend@0.1.32-next.2 + - @backstage/plugin-permission-backend@0.5.17-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.2 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.2 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + - @backstage/plugin-todo-backend@0.1.39-next.2 + +## 0.2.80-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/plugin-tech-insights-backend@0.5.8-next.1 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/plugin-azure-devops-backend@0.3.21-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-kubernetes-backend@0.9.3-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/plugin-playlist-backend@0.2.5-next.1 + - example-app@0.2.80-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-backend@0.2.7-next.1 + - @backstage/plugin-app-backend@0.3.42-next.1 + - @backstage/plugin-auth-backend@0.17.5-next.1 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-azure-sites-backend@0.1.4-next.1 + - @backstage/plugin-badges-backend@0.1.36-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-code-coverage-backend@0.2.8-next.1 + - @backstage/plugin-events-backend@0.2.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + - @backstage/plugin-explore-backend@0.0.4-next.1 + - @backstage/plugin-graphql-backend@0.1.32-next.1 + - @backstage/plugin-jenkins-backend@0.1.32-next.1 + - @backstage/plugin-kafka-backend@0.2.35-next.1 + - @backstage/plugin-permission-backend@0.5.17-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-proxy-backend@0.2.36-next.1 + - @backstage/plugin-rollbar-backend@0.1.39-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.10-next.1 + - @backstage/plugin-search-backend@1.2.3-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.1.3-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.3-next.1 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.26-next.1 + - @backstage/plugin-techdocs-backend@1.5.3-next.1 + - @backstage/plugin-todo-backend@0.1.39-next.1 + ## 0.2.80-next.0 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 27c7a60419..3678c1f9ae 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.80-next.0", + "version": "0.2.80-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,6 +49,7 @@ "@backstage/plugin-jenkins-backend": "workspace:^", "@backstage/plugin-kafka-backend": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", + "@backstage/plugin-lighthouse-backend": "workspace:^", "@backstage/plugin-permission-backend": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index a721c443d6..b68b162e52 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -62,6 +62,7 @@ import jenkins from './plugins/jenkins'; import permission from './plugins/permission'; import playlist from './plugins/playlist'; import adr from './plugins/adr'; +import lighthouse from './plugins/lighthouse'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -148,6 +149,7 @@ async function main() { const playlistEnv = useHotMemoize(module, () => createEnv('playlist')); const eventsEnv = useHotMemoize(module, () => createEnv('events')); const exploreEnv = useHotMemoize(module, () => createEnv('explore')); + const lighthouseEnv = useHotMemoize(module, () => createEnv('lighthouse')); const eventBasedEntityProviders = await catalogEventBasedProviders( catalogEnv, @@ -180,6 +182,8 @@ async function main() { apiRouter.use('/adr', await adr(adrEnv)); apiRouter.use(notFoundHandler()); + await lighthouse(lighthouseEnv); + const service = createServiceBuilder(module) .loadConfig(config) .addRouter('', await healthcheck(healthcheckEnv)) diff --git a/packages/backend/src/plugins/lighthouse.ts b/packages/backend/src/plugins/lighthouse.ts new file mode 100644 index 0000000000..5e805b7b80 --- /dev/null +++ b/packages/backend/src/plugins/lighthouse.ts @@ -0,0 +1,29 @@ +/* + * 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 { createScheduler } from '@backstage/plugin-lighthouse-backend'; +import { PluginEnvironment } from '../types'; +import { CatalogClient } from '@backstage/catalog-client'; + +export default async function createPlugin(env: PluginEnvironment) { + const { logger, scheduler, config } = env; + + const catalogClient = new CatalogClient({ + discoveryApi: env.discovery, + }); + + await createScheduler({ logger, scheduler, config, catalogClient }); +} diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index cf61dee463..1602dfbb79 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/catalog-client +## 1.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/errors@1.1.4 + ## 1.3.1-next.0 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 8b7c09d2ef..ac233e293a 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": "1.3.1-next.0", + "version": "1.3.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 5bb6033940..1f14aba820 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/catalog-model +## 1.2.0-next.1 + +### Minor Changes + +- d51668882d: Adds the tRPC API type to the catalog. + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 1.1.6-next.0 ### Patch Changes diff --git a/packages/catalog-model/examples/all-apis.yaml b/packages/catalog-model/examples/all-apis.yaml index e23f1b3656..472897bfac 100644 --- a/packages/catalog-model/examples/all-apis.yaml +++ b/packages/catalog-model/examples/all-apis.yaml @@ -6,6 +6,7 @@ metadata: spec: targets: - ./apis/hello-world-api.yaml + - ./apis/hello-world-trpc-api.yaml - ./apis/petstore-api.yaml - ./apis/spotify-api.yaml - ./apis/streetlights-api.yaml diff --git a/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml new file mode 100644 index 0000000000..f5807537b3 --- /dev/null +++ b/packages/catalog-model/examples/apis/hello-world-trpc-api.yaml @@ -0,0 +1,25 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world-trpc + description: Hello World example for tRPC +spec: + type: trpc + lifecycle: experimental + owner: team-c + definition: | + import { z } from 'zod'; + import { publicProcedure, router } from '../trpc'; + + export const apiRouter = router({ + version: publicProcedure.query(() => { + return { version: '0.42.0' }; + }), + hello: publicProcedure + .input(z.object({ username: z.string().nullish() }).nullish()) + .query(({ input, ctx }) => { + return { + text: `hello ${input?.username ?? ctx.user?.name ?? 'world'}`, + }; + }), + }); diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index 5dba193a61..117035a82e 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": "1.1.6-next.0", + "version": "1.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json index fae1225764..3d5af710e0 100644 --- a/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json +++ b/packages/catalog-model/src/schema/kinds/API.v1alpha1.schema.json @@ -46,7 +46,7 @@ "type": { "type": "string", "description": "The type of the API definition.", - "examples": ["openapi", "asyncapi", "graphql", "grpc"], + "examples": ["openapi", "asyncapi", "graphql", "grpc", "trpc"], "minLength": 1 }, "lifecycle": { diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 25a0704f56..09e7f44eb4 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/cli +## 0.22.2-next.1 + +### Patch Changes + +- dd8a9afe66: Replaced several monorepo lint rules with new rules from `@backstage/eslint-plugin`. See the [README](https://github.com/import-js/eslint-plugin-import/blob/main/packages/eslint-plugin/README.md) for a full list of rules. +- 90616df9a8: Added an experimental mode for the `package start` command for backend packages. Enabled by setting `EXPERIMENTAL_BACKEND_START`. +- Updated dependencies + - @backstage/eslint-plugin@0.1.0-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + +## 0.22.2-next.0 + +### Patch Changes + +- 561df21ea3: The `backstage-cli repo test` command now sets a default Jest `--workerIdleMemoryLimit` of 1GB. If needed to ensure that tests are not run in band, `--maxWorkers=2` is set as well. This is the recommended workaround for dealing with Jest workers leaking memory and eventually hitting the heap limit. +- 2815981057: Show module name causing error during build +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- 6d3abfded1: Switch to inline source maps for test transpilation, simplifying editor setups. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/errors@1.1.4 + - @backstage/release-manifests@0.0.8 + - @backstage/types@1.0.2 + ## 0.22.1 ### Patch Changes diff --git a/packages/cli/asset-types/asset-types.d.ts b/packages/cli/asset-types/asset-types.d.ts index 0bd0922004..9bd158bb8e 100644 --- a/packages/cli/asset-types/asset-types.d.ts +++ b/packages/cli/asset-types/asset-types.d.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /// /// diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index a40aa79fb3..dde853fdff 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -60,7 +60,7 @@ function createConfig(dir, extraConfig = {}) { '@spotify/eslint-config-typescript', 'prettier', 'plugin:jest/recommended', - 'plugin:monorepo/recommended', + 'plugin:@backstage/recommended', ...(extraExtends ?? []), ], parser: '@typescript-eslint/parser', @@ -88,32 +88,6 @@ function createConfig(dir, extraConfig = {}) { '@typescript-eslint/no-redeclare': 'error', 'no-undef': 'off', 'import/newline-after-import': 'error', - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: dir - ? [ - `!${joinPath(dir, 'src/**')}`, - joinPath(dir, 'src/**/*.test.*'), - joinPath(dir, 'src/**/*.stories.*'), - joinPath(dir, 'src/**/__testUtils__/**'), - joinPath(dir, 'src/**/__mocks__/**'), - joinPath(dir, 'src/setupTests.*'), - ] - : [ - // Legacy config for packages that don't provide a dir - '**/*.test.*', - '**/*.stories.*', - '**/__testUtils__/**', - '**/__mocks__/**', - '**/src/setupTests.*', - '**/dev/**', - ], - optionalDependencies: true, - peerDependencies: true, - bundledDependencies: true, - }, - ], 'no-unused-expressions': 'off', '@typescript-eslint/no-unused-expressions': 'error', '@typescript-eslint/consistent-type-assertions': 'error', @@ -135,9 +109,6 @@ function createConfig(dir, extraConfig = {}) { ...(restrictedSrcImports ?? []), ], patterns: [ - // Avoid cross-package imports - '**/../../**/*/src/**', - '**/../../**/*/src', // Prevent imports of stories or tests '*.stories*', '*.test*', @@ -187,8 +158,6 @@ function createConfig(dir, extraConfig = {}) { ...(restrictedImports ?? []), ...(restrictedTestImports ?? []), ], - // Avoid cross-package imports - patterns: ['**/../../**/*/src/**', '**/../../**/*/src'], }, ], }, diff --git a/packages/cli/package.json b/packages/cli/package.json index 59bb880ffb..a3020de1da 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.22.1", + "version": "0.22.2-next.1", "publishConfig": { "access": "public" }, @@ -34,8 +34,10 @@ "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/eslint-plugin": "workspace:^", "@backstage/release-manifests": "workspace:^", "@backstage/types": "workspace:^", + "@esbuild-kit/cjs-loader": "^2.4.1", "@manypkg/get-packages": "^1.1.3", "@octokit/request": "^6.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", @@ -65,6 +67,7 @@ "chalk": "^4.0.0", "chokidar": "^3.3.1", "commander": "^9.1.0", + "cross-spawn": "^7.0.3", "css-loader": "^6.5.1", "diff": "^5.0.0", "esbuild": "^0.17.0", @@ -76,7 +79,6 @@ "eslint-plugin-import": "^2.25.4", "eslint-plugin-jest": "^27.0.0", "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-monorepo": "^0.3.2", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", "eslint-webpack-plugin": "^3.1.1", @@ -136,6 +138,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", + "@types/cross-spawn": "^6.0.2", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", "@types/fs-extra": "^9.0.1", diff --git a/packages/cli/src/commands/start/startBackend.ts b/packages/cli/src/commands/start/startBackend.ts index 61ada7a291..3e6a13be96 100644 --- a/packages/cli/src/commands/start/startBackend.ts +++ b/packages/cli/src/commands/start/startBackend.ts @@ -17,6 +17,7 @@ import fs from 'fs-extra'; import { paths } from '../../lib/paths'; import { serveBackend } from '../../lib/bundler'; +import { startBackendExperimental } from '../../lib/experimental/startBackendExperimental'; interface StartBackendOptions { checksEnabled: boolean; @@ -25,17 +26,28 @@ interface StartBackendOptions { } export async function startBackend(options: StartBackendOptions) { - // Cleaning dist/ before we start the dev process helps work around an issue - // where we end up with the entrypoint executing multiple times, causing - // a port bind conflict among other things. - await fs.remove(paths.resolveTarget('dist')); + if (process.env.EXPERIMENTAL_BACKEND_START) { + const waitForExit = await startBackendExperimental({ + entry: 'src/index', + checksEnabled: false, // not supported + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); - const waitForExit = await serveBackend({ - entry: 'src/index', - checksEnabled: options.checksEnabled, - inspectEnabled: options.inspectEnabled, - inspectBrkEnabled: options.inspectBrkEnabled, - }); + await waitForExit(); + } else { + // Cleaning dist/ before we start the dev process helps work around an issue + // where we end up with the entrypoint executing multiple times, causing + // a port bind conflict among other things. + await fs.remove(paths.resolveTarget('dist')); - await waitForExit(); + const waitForExit = await serveBackend({ + entry: 'src/index', + checksEnabled: options.checksEnabled, + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); + + await waitForExit(); + } } diff --git a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts index 2533131a40..cf37c2a664 100644 --- a/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts +++ b/packages/cli/src/lib/builder/buildTypeDefinitionsWorker.ts @@ -50,7 +50,7 @@ export async function buildTypeDefinitionsWorker( */ const { PackageJsonLookup, - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-undeclared-imports } = require('@rushstack/node-core-library/lib/PackageJsonLookup'); const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor; diff --git a/packages/cli/src/lib/bundler/transforms.ts b/packages/cli/src/lib/bundler/transforms.ts index 9a93f550dd..e0308f5c2d 100644 --- a/packages/cli/src/lib/bundler/transforms.ts +++ b/packages/cli/src/lib/bundler/transforms.ts @@ -107,7 +107,7 @@ export const transforms = (options: TransformOptions): Transforms => { ], }, { - test: /\.(js|mjs|cjs)/, + test: /\.(js|mjs|cjs)$/, resolve: { fullySpecified: false, }, @@ -141,9 +141,10 @@ export const transforms = (options: TransformOptions): Transforms => { /\.gif$/, /\.jpe?g$/, /\.png$/, - /\.frag/, - { and: [/\.svg/, { not: [/\.icon\.svg/] }] }, - /\.xml/, + /\.frag$/, + /\.vert$/, + { and: [/\.svg$/, { not: [/\.icon\.svg$/] }] }, + /\.xml$/, ], type: 'asset/resource', generator: { diff --git a/packages/cli/src/lib/experimental/IpcServer.ts b/packages/cli/src/lib/experimental/IpcServer.ts new file mode 100644 index 0000000000..8ceb72b046 --- /dev/null +++ b/packages/cli/src/lib/experimental/IpcServer.ts @@ -0,0 +1,102 @@ +/* + * Copyright 2023 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 { serializeError } from '@backstage/errors'; +import { ChildProcess } from 'child_process'; + +interface RequestMeta { + generation: number; +} + +type MethodHandler = ( + req: TRequest, + meta: RequestMeta, +) => Promise; + +interface Request { + id: number; + method: string; + body: unknown; + type: string; +} + +const requestType = '@backstage/cli/channel/request'; +const responseType = '@backstage/cli/channel/response'; + +export class IpcServer { + #generation = 1; + #methods = new Map>(); + + addChild(child: ChildProcess) { + const generation = this.#generation++; + const sendMessage = child.send?.bind(child); + if (!sendMessage) { + return; + } + + const messageListener = (request: Request) => { + if (request.type !== requestType) { + return; + } + + const handler = this.#methods.get(request.method); + if (!handler) { + sendMessage({ + type: responseType, + id: request.id, + error: { + name: 'NotFoundError', + message: `No handler registered for method ${request.method}`, + }, + }); + return; + } + + Promise.resolve() + .then(() => handler(request.body, { generation })) + .then(response => + sendMessage({ + type: responseType, + id: request.id, + body: response, + }), + ) + .catch(error => + sendMessage({ + type: responseType, + id: request.id, + error: serializeError(error), + }), + ); + }; + + child.addListener('message', messageListener as (req: unknown) => void); + + child.addListener('exit', () => { + child.removeListener('message', messageListener); + }); + } + + registerMethod( + method: string, + handler: MethodHandler, + ) { + if (this.#methods.has(method)) { + throw new Error(`A handler is already registered for method ${method}`); + } + this.#methods.set(method, handler); + } +} diff --git a/packages/cli/src/lib/experimental/ServerDataStore.ts b/packages/cli/src/lib/experimental/ServerDataStore.ts new file mode 100644 index 0000000000..c0232157cb --- /dev/null +++ b/packages/cli/src/lib/experimental/ServerDataStore.ts @@ -0,0 +1,78 @@ +/* + * Copyright 2023 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 { IpcServer } from './IpcServer'; + +interface StorageItem { + generation: number; + data: unknown; +} + +interface SaveRequest { + key: string; + data: unknown; +} + +interface SaveResponse { + saved: boolean; +} + +interface LoadRequest { + key: string; +} + +interface LoadResponse { + loaded: boolean; + data: unknown; +} + +export class ServerDataStore { + static bind(server: IpcServer): void { + const store = new Map(); + + server.registerMethod( + 'DevDataStore.save', + async (request, { generation }) => { + const { key, data } = request; + if (!key) { + throw new Error('Key is required in DevDataStore.save'); + } + + const item = store.get(key); + + if (!item) { + store.set(key, { generation, data }); + return { saved: true }; + } + + if (item.generation > generation) { + return { saved: false }; + } + + store.set(key, { generation, data }); + return { saved: true }; + }, + ); + + server.registerMethod( + 'DevDataStore.load', + async request => { + const item = store.get(request.key); + return { loaded: Boolean(item), data: item?.data }; + }, + ); + } +} diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts new file mode 100644 index 0000000000..c08fbda0da --- /dev/null +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -0,0 +1,138 @@ +/* + * 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 { BackendServeOptions } from '../bundler/types'; +import type { ChildProcess } from 'child_process'; +import { fileURLToPath } from 'url'; +import { isAbsolute as isAbsolutePath } from 'path'; +import { FSWatcher, watch } from 'chokidar'; +import { IpcServer } from './IpcServer'; +import { ServerDataStore } from './ServerDataStore'; +import debounce from 'lodash/debounce'; +import spawn from 'cross-spawn'; +import { paths } from '../paths'; + +const loaderArgs = ['--require', require.resolve('@esbuild-kit/cjs-loader')]; + +export async function startBackendExperimental(options: BackendServeOptions) { + const envEnv = process.env as { NODE_ENV: string }; + if (!envEnv.NODE_ENV) { + envEnv.NODE_ENV = 'development'; + } + + // Set up the parent IPC server and bind the available services + const server = new IpcServer(); + ServerDataStore.bind(server); + + let exiting = false; + let child: ChildProcess | undefined; + let watcher: FSWatcher | undefined = undefined; + let shutdownPromise: Promise | undefined = undefined; + + const restart = debounce(async () => { + // If a re-trigger happens during an existing shutdown, we just ignore it + if (shutdownPromise) { + return; + } + + if (child && !child.killed && child.exitCode === null) { + // We always wait for the existing process to exit, to make sure we don't get IPC conflicts + shutdownPromise = new Promise(resolve => child!.once('exit', resolve)); + child.kill(); + await shutdownPromise; + shutdownPromise = undefined; + } + + // We've received a shutdown signal + if (exiting) { + return; + } + + const optionArgs = new Array(); + if (options.inspectEnabled) { + optionArgs.push('--inspect'); + } else if (options.inspectBrkEnabled) { + optionArgs.push('--inspect-brk'); + } + + const userArgs = process.argv + .slice(['node', 'backstage-cli', 'package', 'start'].length) + .filter(arg => !optionArgs.includes(arg)); + + child = spawn( + process.execPath, + [...loaderArgs, ...optionArgs, options.entry, ...userArgs], + { + stdio: ['inherit', 'inherit', 'inherit', 'ipc'], + env: { + ...process.env, + BACKSTAGE_CLI_CHANNEL: '1', + ESBK_TSCONFIG_PATH: paths.resolveTargetRoot('tsconfig.json'), + }, + serialization: 'advanced', + }, + ); + + server.addChild(child); + + // This captures messages sent by @esbuild-kit/cjs-loader + child.on('message', (data: { type?: string } | null) => { + if (typeof data === 'object' && data?.type === 'dependency') { + let path = (data as { path: string }).path; + if (path.startsWith('file:')) { + path = fileURLToPath(path); + } + + if (isAbsolutePath(path)) { + watcher?.add(path); + } + } + }); + }, 100); + + restart(); + + watcher = watch([paths.targetDir], { + cwd: process.cwd(), + ignored: ['**/.*/**', '**/node_modules/**'], + ignoreInitial: true, + ignorePermissionErrors: true, + }).on('all', restart); + + // Trigger restart on hitting enter in the terminal + process.stdin.on('data', restart); + + const exitPromise = new Promise(resolveExitPromise => { + async function handleSignal(signal: NodeJS.Signals) { + exiting = true; + + // Forward signals to child and wait for it to exit if still running + if (child && child.exitCode === null) { + await new Promise(resolve => { + child!.on('close', resolve); + child!.kill(signal); + }); + } + + resolveExitPromise(); + } + + process.once('SIGINT', handleSignal); + process.once('SIGTERM', handleSignal); + }); + + return () => exitPromise; +} diff --git a/packages/cli/src/lib/version.test.ts b/packages/cli/src/lib/version.test.ts index fb9bf83e7c..604129679b 100644 --- a/packages/cli/src/lib/version.test.ts +++ b/packages/cli/src/lib/version.test.ts @@ -17,7 +17,6 @@ import mockFs from 'mock-fs'; import { packageVersions, createPackageVersionProvider } from './version'; import { Lockfile } from './versioning'; -// eslint-disable-next-line monorepo/no-internal-import import corePluginApiPkg from '@backstage/core-plugin-api/package.json'; describe('createPackageVersionProvider', () => { diff --git a/packages/cli/src/lib/version.ts b/packages/cli/src/lib/version.ts index 5a199236f5..bf89842d5f 100644 --- a/packages/cli/src/lib/version.ts +++ b/packages/cli/src/lib/version.ts @@ -19,7 +19,7 @@ import semver from 'semver'; import { paths } from './paths'; import { Lockfile } from './versioning'; -/* eslint-disable monorepo/no-relative-import */ +/* eslint-disable @backstage/no-relative-monorepo-imports */ /* This is a list of all packages used by the templates. If dependencies are added or removed, diff --git a/packages/cli/src/types.d.ts b/packages/cli/src/types.d.ts index fedbe61f02..1222b2b4b8 100644 --- a/packages/cli/src/types.d.ts +++ b/packages/cli/src/types.d.ts @@ -258,3 +258,5 @@ declare module 'webpack-node-externals' { } } } + +declare module '@esbuild-kit/cjs-loader' {} diff --git a/packages/codemods/.eslintrc.js b/packages/codemods/.eslintrc.js index f9fb2e27c9..e2a53a6ad2 100644 --- a/packages/codemods/.eslintrc.js +++ b/packages/codemods/.eslintrc.js @@ -1,14 +1 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { - rules: { - 'no-console': 0, - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: false, - peerDependencies: false, - bundledDependencies: false, - }, - ], - }, -}); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 2481aff8b1..5dc610d5c1 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/codemods +## 0.1.43-next.0 + +### Patch Changes + +- 02f1316e57: Moved `commander` to being a regular dependency. +- Updated dependencies + - @backstage/cli-common@0.1.11 + ## 0.1.42 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index cbcc0613d4..7c6af890b0 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.42", + "version": "0.1.43-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" @@ -35,6 +35,7 @@ "dependencies": { "@backstage/cli-common": "workspace:^", "chalk": "^4.0.0", + "commander": "^9.1.0", "jscodeshift": "^0.14.0", "jscodeshift-add-imports": "^1.0.10" }, @@ -42,7 +43,6 @@ "@backstage/cli": "workspace:^", "@types/jscodeshift": "^0.11.0", "@types/node": "^16.11.26", - "commander": "^9.1.0", "ts-node": "^10.0.0" }, "nodemonConfig": { diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 0d059f7b46..1d682dbc4a 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/core-app-api +## 1.4.1-next.0 + +### Patch Changes + +- dff4d8ddb1: Fixed an issue where an explicit port the frontend base URL could break the app. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + ## 1.4.0 ### Minor Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 330405d853..391771bd5c 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.4.0", + "version": "1.4.1-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index a46acb0897..30c4e92173 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/core-components +## 0.12.4-next.1 + +### Patch Changes + +- 66e2aab4c4: Navigation items in mobile sidebar now have aria label. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + +## 0.12.4-next.0 + +### Patch Changes + +- 910015f5b7: The Button component has been deprecated in favor of the LinkButton component +- 20840b36b4: Adds new type, TableOptions, extending Material Table Options. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/version-bridge@1.0.3 + ## 0.12.3 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 72f8b069bf..7eedac93ac 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.12.3", + "version": "0.12.4-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/core-components/src/components/LogViewer/LogLine.tsx b/packages/core-components/src/components/LogViewer/LogLine.tsx index 8f3a2ce65c..c8ff5cbceb 100644 --- a/packages/core-components/src/components/LogViewer/LogLine.tsx +++ b/packages/core-components/src/components/LogViewer/LogLine.tsx @@ -15,7 +15,6 @@ */ import React, { useMemo } from 'react'; -import Typography from '@material-ui/core/Typography'; import { AnsiChunk, AnsiLine, ChunkModifiers } from './AnsiProcessor'; import startCase from 'lodash/startCase'; import classnames from 'classnames'; @@ -159,8 +158,8 @@ export function LogLine({ const elements = useMemo( () => chunks.map(({ text, modifiers, highlight }, index) => ( - {text} - + )), [chunks, highlightResultIndex, classes], ); diff --git a/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx b/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx index dd707778e1..e1aac76381 100644 --- a/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx +++ b/packages/core-components/src/components/LogViewer/RealLogViewer.test.tsx @@ -18,7 +18,7 @@ import React, { ReactNode } from 'react'; import userEvent from '@testing-library/user-event'; import { renderInTestApp } from '@backstage/test-utils'; import { RealLogViewer } from './RealLogViewer'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import copyToClipboard from 'copy-to-clipboard'; // Used by useCopyToClipboard diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx index 7e00d50f33..93a6dfd7e9 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, MockErrorApi } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; import { AnsiLine } from './AnsiProcessor'; import { useLogViewerSelection } from './useLogViewerSelection'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import copyToClipboard from 'copy-to-clipboard'; // Used by useCopyToClipboard diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 7bb9aab9b5..35cf228f52 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -16,8 +16,6 @@ import { useApp } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { makeStyles } from '@material-ui/core/styles'; -import useMediaQuery from '@material-ui/core/useMediaQuery'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import DialogActions from '@material-ui/core/DialogActions'; @@ -27,7 +25,9 @@ import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import Popover from '@material-ui/core/Popover'; +import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; import React, { MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { HelpIcon } from '../../icons'; @@ -111,13 +111,14 @@ export function SupportButton(props: SupportButtonProps) { size="small" onClick={onClickHandler} data-testid="support-button" + aria-label="Support" > ) : ( diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index 95d474aae4..3d8d0f3bb0 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -188,12 +188,12 @@ export function InfoCard(props: Props): JSX.Element { variants.forEach(name => { calculatedStyle = { ...calculatedStyle, - ...VARIANT_STYLES.card[name as keyof typeof VARIANT_STYLES['card']], + ...VARIANT_STYLES.card[name as keyof (typeof VARIANT_STYLES)['card']], }; calculatedCardStyle = { ...calculatedCardStyle, ...VARIANT_STYLES.cardContent[ - name as keyof typeof VARIANT_STYLES['cardContent'] + name as keyof (typeof VARIANT_STYLES)['cardContent'] ], }; }); diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 5254199563..1eb1423c61 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -23,7 +23,7 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { useContext } from 'react'; import { useLocation } from 'react-router-dom'; import { Link } from '../../components'; -import { SidebarConfigContext, SidebarConfig } from './config'; +import { SidebarConfig, SidebarConfigContext } from './config'; import { MobileSidebarContext } from './MobileSidebar'; import { useSidebarPinState } from './SidebarPinStateContext'; @@ -100,6 +100,7 @@ const MobileSidebarGroup = (props: SidebarGroupProps) => { return ( // Material UI issue: https://github.com/mui-org/material-ui/issues/27820 , files?: Array }}} packageJson + */ + +/** + * @typedef PackageMap + * @type object + * + * @property {ExtendedPackage} root + * @property {ExtendedPackage[]} list + * @property {Map} map + * @property {(path: string) => ExtendedPackage | undefined} byPath + */ + +// Loads all packages in the monorepo once, and caches the result +module.exports = (function () { + /** @type {PackageMap | undefined} */ + let result = undefined; + /** @type {number} */ + let lastLoadAt = 0; + + /** @returns {PackageMap | undefined} */ + return function getPackages(/** @type {string} */ dir) { + if (result) { + // Only cache for 5 seconds, to avoid the need to reload ESLint servers + if (Date.now() - lastLoadAt > 5000) { + result = undefined; + } else { + return result; + } + } + const packages = manypkg.getPackagesSync(dir); + if (!packages) { + return undefined; + } + result = { + map: new Map(packages.packages.map(pkg => [pkg.packageJson.name, pkg])), + list: packages.packages, + root: packages.root, + byPath(filePath) { + return packages.packages.find( + pkg => !path.relative(pkg.dir, filePath).startsWith('..'), + ); + }, + }; + lastLoadAt = Date.now(); + return result; + }; +})(); diff --git a/packages/eslint-plugin/lib/visitImports.js b/packages/eslint-plugin/lib/visitImports.js new file mode 100644 index 0000000000..43401bf5f9 --- /dev/null +++ b/packages/eslint-plugin/lib/visitImports.js @@ -0,0 +1,173 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const { builtinModules } = require('module'); +const getPackages = require('./getPackages'); + +/** + * @typedef LocalImport + * @type {object} + * @property {'local'} type + * @property {'value' | 'type'} kind + * @property {string} path + */ + +/** + * @typedef InternalImport + * @type {object} + * @property {'internal'} type + * @property {'value' | 'type'} kind + * @property {string} path + * @property {import('./getPackages').ExtendedPackage} package + */ + +/** + * @typedef ExternalImport + * @type {object} + * @property {'external'} type + * @property {'value' | 'type'} kind + * @property {string} path + * @property {string} packageName + */ + +/** + * @typedef BuiltinImport + * @type {object} + * @property {'builtin'} type + * @property {'value' | 'type'} kind + * @property {string} path + * @property {string} packageName + */ + +/** + * @callback ImportVisitor + * @param {ConsideredNode} node + * @param {LocalImport | InternalImport | ExternalImport | BuiltinImport} import + */ + +/** + * @typedef ConsideredNode + * @type {import('estree').ImportDeclaration | import('estree').ExportAllDeclaration | import('estree').ExportNamedDeclaration | import('estree').ImportExpression | import('estree').SimpleCallExpression} + */ + +/** + * @param {ConsideredNode} node + * @returns {undefined | {path: string, kind: 'type' | 'value'}} + */ +function getImportInfo(node) { + /** @type {import('estree').Expression | import('estree').SpreadElement | undefined | null} */ + let pathNode; + + if (node.type === 'CallExpression') { + if ( + node.callee.type === 'Identifier' && + node.callee.name == 'require' && + node.arguments.length === 1 + ) { + pathNode = node.arguments[0]; + } + } else { + pathNode = node.source; + } + + if (pathNode?.type !== 'Literal') { + return undefined; + } + if (typeof pathNode.value !== 'string') { + return undefined; + } + + /** @type {any} */ + const anyNode = node; + return { path: pathNode.value, kind: anyNode.importKind ?? 'value' }; +} + +/** + * @param visitor - Visitor callback + * @param {import('eslint').Rule.RuleContext} context + * @param {ImportVisitor} visitor + */ +module.exports = function visitImports(context, visitor) { + const packages = getPackages(context.getCwd()); + if (!packages) { + return; + } + + /** + * @param {ConsideredNode} node + */ + function visit(node) { + const info = getImportInfo(node); + if (!info) { + return; + } + + if (info.path[0] === '.') { + return visitor(node, { type: 'local', ...info }); + } + + const pathParts = info.path.split('/'); + + // Check for match with plain name, then namespaced name + let packageName; + let subPath; + if (info.path[0] === '@') { + packageName = pathParts.slice(0, 2).join('/'); + subPath = pathParts.slice(2).join('/'); + } else { + packageName = pathParts[0]; + subPath = pathParts.slice(1).join('/'); + } + const pkg = packages?.map.get(packageName); + if (!pkg) { + if ( + packageName.startsWith('node:') || + builtinModules.includes(packageName) + ) { + return visitor(node, { + type: 'builtin', + kind: info.kind, + path: subPath, + packageName, + }); + } + + return visitor(node, { + type: 'external', + kind: info.kind, + path: subPath, + packageName, + }); + } + + return visitor(node, { + type: 'internal', + kind: info.kind, + path: subPath, + package: pkg, + }); + } + + return { + ImportDeclaration: visit, + ExportAllDeclaration: visit, + ExportNamedDeclaration: visit, + ImportExpression: visit, + CallExpression: visit, + }; +}; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json new file mode 100644 index 0000000000..0aea11d370 --- /dev/null +++ b/packages/eslint-plugin/package.json @@ -0,0 +1,28 @@ +{ + "name": "@backstage/eslint-plugin", + "description": "Backstage ESLint plugin", + "version": "0.1.0-next.0", + "publishConfig": { + "access": "public" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/eslint-plugin" + }, + "license": "Apache-2.0", + "main": "./index.js", + "scripts": { + "lint": "backstage-cli package lint", + "test": "backstage-cli package test" + }, + "dependencies": { + "@manypkg/get-packages": "^1.1.3", + "minimatch": "^5.1.2" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "eslint": "^8.33.0" + } +} diff --git a/packages/eslint-plugin/rules/no-forbidden-package-imports.js b/packages/eslint-plugin/rules/no-forbidden-package-imports.js new file mode 100644 index 0000000000..e7c1acca27 --- /dev/null +++ b/packages/eslint-plugin/rules/no-forbidden-package-imports.js @@ -0,0 +1,74 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const visitImports = require('../lib/visitImports'); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + messages: { + forbidden: '{{packageName}} does not export {{subPath}}', + }, + docs: { + description: + 'Disallow internal monorepo imports from package subpaths that are not exported.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-forbidden-package-imports.md', + }, + }, + create(context) { + return visitImports(context, (node, imp) => { + if (imp.type !== 'internal') { + return; + } + // Empty subpaths are always allowed + if (!imp.path) { + return; + } + + // If the import is listed in the package.json exports field, we allow it + const exp = imp.package.packageJson.exports; + if (exp && (exp[imp.path] || exp['./' + imp.path])) { + return; + } + if (!exp) { + // If there's no exports field, we allow anything listed in files, except dist + const files = imp.package.packageJson.files; + if ( + !files || + files.some(f => !f.startsWith('dist') && imp.path.startsWith(f)) + ) { + return; + } + // And also package.json + if (imp.path === 'package.json') { + return; + } + } + + context.report({ + node: node, + messageId: 'forbidden', + data: { + packageName: imp.package.packageJson.name || imp.package.dir, + subPath: imp.path, + }, + }); + }); + }, +}; diff --git a/packages/eslint-plugin/rules/no-relative-monorepo-imports.js b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js new file mode 100644 index 0000000000..df30d35f67 --- /dev/null +++ b/packages/eslint-plugin/rules/no-relative-monorepo-imports.js @@ -0,0 +1,85 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const path = require('path'); +const visitImports = require('../lib/visitImports'); +const getPackageMap = require('../lib/getPackages'); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + messages: { + outside: 'Import of {{path}} is outside of any known monorepo package', + forbidden: + "Relative imports of monorepo packages are forbidden, use '{{newImport}}' instead", + }, + docs: { + description: + 'Forbid relative imports that reach outside of the package in a monorepo.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-relative-monorepo-imports.md', + }, + }, + create(context) { + const packages = getPackageMap(context.getCwd()); + if (!packages) { + return {}; + } + const filePath = context.getPhysicalFilename + ? context.getPhysicalFilename() + : context.getFilename(); + + const localPkg = packages.byPath(filePath); + if (!localPkg) { + return {}; + } + + return visitImports(context, (node, imp) => { + if (imp.type !== 'local') { + return; + } + + const target = path.resolve(path.dirname(filePath), imp.path); + if (!path.relative(localPkg.dir, target).startsWith('..')) { + return; + } + + const targetPkg = packages.byPath(target); + if (!targetPkg) { + context.report({ + node: node, + messageId: 'outside', + data: { + path: target, + }, + }); + return; + } + + const targetPath = path.relative(targetPkg.dir, target); + const targetName = targetPkg.packageJson.name ?? ''; + context.report({ + node: node, + messageId: 'forbidden', + data: { + newImport: targetPath ? `${targetName}/${targetPath}` : targetName, + }, + }); + }); + }, +}; diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js new file mode 100644 index 0000000000..42624beb5c --- /dev/null +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -0,0 +1,205 @@ +/* + * Copyright 2023 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. + */ + +// @ts-check + +const path = require('path'); +const getPackageMap = require('../lib/getPackages'); +const visitImports = require('../lib/visitImports'); +const minimatch = require('minimatch'); + +const depFields = { + dep: 'dependencies', + dev: 'devDependencies', + peer: 'peerDependencies', +}; + +const devModulePatterns = [ + new minimatch.Minimatch('!src/**'), + new minimatch.Minimatch('src/**/*.test.*'), + new minimatch.Minimatch('src/**/*.stories.*'), + new minimatch.Minimatch('src/**/__testUtils__/**'), + new minimatch.Minimatch('src/**/__mocks__/**'), + new minimatch.Minimatch('src/setupTests.*'), +]; + +function getExpectedDepType( + /** @type {any} */ localPkg, + /** @type {string} */ impPath, + /** @type {string} */ modulePath, +) { + const role = localPkg?.backstage?.role; + // Some package roles have known dependency types + switch (role) { + case 'common-library': + case 'web-library': + case 'frontend-plugin': + case 'frontend-plugin-module': + case 'node-library': + case 'backend-plugin': + case 'backend-plugin-module': + switch (impPath) { + case 'react': + case 'react-dom': + case 'react-router': + case 'react-router-dom': + return 'peer'; + } + break; + case 'cli': + case 'frontend': + case 'backend': + default: + break; + } + + for (const pattern of devModulePatterns) { + if (pattern.match(modulePath)) { + return 'dev'; + } + } + return 'dep'; +} + +/** + * + * @param {import('@manypkg/get-packages').Package['packageJson']} pkg + * @param {string} name + * @param {ReturnType} expectedType + * @returns {{oldDepsField?: string, depsField: string} | undefined} + */ +function findConflict(pkg, name, expectedType) { + const isDep = pkg.dependencies?.[name]; + const isDevDep = pkg.devDependencies?.[name]; + const isPeerDep = pkg.peerDependencies?.[name]; + const depsField = depFields[expectedType]; + + if (expectedType === 'dep' && !isDep && !isPeerDep) { + const oldDepsField = isDevDep ? depFields.dev : undefined; + return { oldDepsField, depsField }; + } else if (expectedType === 'dev' && !isDevDep && !isDep && !isPeerDep) { + return { oldDepsField: undefined, depsField }; + } else if (expectedType === 'peer' && !isPeerDep) { + const oldDepsField = isDep + ? depFields.dep + : isDevDep + ? depFields.dev + : undefined; + + return { oldDepsField, depsField }; + } + return undefined; +} + +/** + * @param {string} depsField + */ +function getAddFlagForDepsField(depsField) { + switch (depsField) { + case depFields.dep: + return ''; + case depFields.dev: + return ' --dev'; + case depFields.peer: + return ' --peer'; + default: + return ''; + } +} + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + messages: { + undeclared: + "{{ packageName }} must be declared in {{ depsField }} of {{ packageJsonPath }}, run 'yarn --cwd {{ packagePath }} add{{ addFlag }} {{ packageName }}' from the project root.", + switch: + '{{ packageName }} is declared in {{ oldDepsField }}, but should be moved to {{ depsField }} in {{ packageJsonPath }}.', + }, + docs: { + description: + 'Forbid imports of external packages that have not been declared in the appropriate dependencies field in `package.json`.', + url: 'https://github.com/backstage/backstage/blob/master/packages/eslint-plugin/docs/rules/no-undeclared-imports.md', + }, + }, + create(context) { + const packages = getPackageMap(context.getCwd()); + if (!packages) { + return {}; + } + const filePath = context.getPhysicalFilename + ? context.getPhysicalFilename() + : context.getFilename(); + + const localPkg = packages.byPath(filePath); + if (!localPkg) { + return {}; + } + + return visitImports(context, (node, imp) => { + if (imp.type !== 'external') { + return; + } + // We leave checking of type imports to the repo-tools check + if (imp.kind === 'type') { + return; + } + + const modulePath = path.relative(localPkg.dir, filePath); + const expectedType = getExpectedDepType( + localPkg.packageJson, + imp.packageName, + modulePath, + ); + + const conflict = findConflict( + localPkg.packageJson, + imp.packageName, + expectedType, + ); + + if (conflict) { + try { + const fullImport = imp.path + ? `${imp.packageName}/${imp.path}` + : imp.packageName; + require.resolve(fullImport, { + paths: [localPkg.dir], + }); + } catch { + // If the dependency doesn't resolve then it's likely a type import, ignore + return; + } + + const packagePath = path.relative(packages.root.dir, localPkg.dir); + const packageJsonPath = path.join(packagePath, 'package.json'); + + context.report({ + node, + messageId: conflict.oldDepsField ? 'switch' : 'undeclared', + data: { + ...conflict, + packagePath, + addFlag: getAddFlagForDepsField(conflict.depsField), + packageName: imp.packageName, + packageJsonPath: packageJsonPath, + }, + }); + } + }); + }, +}; diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/package.json new file mode 100644 index 0000000000..c35178c46f --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/package.json @@ -0,0 +1,6 @@ +{ + "name": "root", + "workspaces": [ + "packages/*" + ] +} diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json new file mode 100644 index 0000000000..efef27047b --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json @@ -0,0 +1,17 @@ +{ + "name": "@internal/bar", + "exports": { + ".": "./src/index.ts", + "./BarPage": "./src/components/Bar.tsx", + "./package.json": "./package.json" + }, + "backstage": { + "role": "frontend-plugin" + }, + "dependencies": { + "react-router": "*" + }, + "devDependencies": { + "react-router-dom": "*" + } +} diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json new file mode 100644 index 0000000000..563ec35120 --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json @@ -0,0 +1,16 @@ +{ + "name": "@internal/foo", + "dependencies": { + "@internal/bar": "1.0.0" + }, + "devDependencies": { + "lodash": "*" + }, + "peerDependencies": { + "react": "*" + }, + "files": [ + "dist", + "type-utils" + ] +} diff --git a/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts b/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts new file mode 100644 index 0000000000..349b71319f --- /dev/null +++ b/packages/eslint-plugin/src/no-forbidden-package-imports.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import path from 'path'; +import rule from '../rules/no-forbidden-package-imports'; + +const RULE = 'no-forbidden-package-imports'; +const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); + +const ERR = (name: string, path: string) => ({ + message: `${name} does not export ${path}`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import '@internal/foo'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/type-utils'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/type-utils/anything'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/foo/package.json'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar/package.json'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + { + code: `import '@internal/bar/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + }, + ], + invalid: [ + { + code: `import '@internal/foo/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'FooPage')], + }, + { + code: `import '@internal/foo/dist'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'dist')], + }, + { + code: `import '@internal/foo/dist/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'dist/FooPage')], + }, + { + code: `import '@internal/foo/src/FooPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'src/FooPage')], + }, + { + code: `import '@internal/foo/src'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/foo', 'src')], + }, + { + code: `import '@internal/bar/OtherBarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'OtherBarPage')], + }, + { + code: `import '@internal/bar/dist'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'dist')], + }, + { + code: `import '@internal/bar/dist/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'dist/BarPage')], + }, + { + code: `import '@internal/bar/src/BarPage'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'src/BarPage')], + }, + { + code: `import '@internal/bar/src'`, + filename: path.join(FIXTURE, 'index.ts'), + errors: [ERR('@internal/bar', 'src')], + }, + ], +}); diff --git a/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts b/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts new file mode 100644 index 0000000000..6888d258cc --- /dev/null +++ b/packages/eslint-plugin/src/no-relative-monorepo-imports.test.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import path from 'path'; +import rule from '../rules/no-relative-monorepo-imports'; + +const RULE = 'no-relative-monorepo-imports'; +const FIXTURE = path.resolve(__dirname, '__fixtures__/monorepo'); + +const ERR_OUTSIDE = (path: string) => ({ + message: `Import of ${path} is outside of any known monorepo package`, +}); +const ERR_FORBIDDEN = (newImp: string) => ({ + message: `Relative imports of monorepo packages are forbidden, use '${newImp}' instead`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import { version } from '@internal/foo'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + }, + { + code: `import { version } from '@internal/foo/src'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + }, + ], + invalid: [ + { + code: `import { version } from '../../foo'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_FORBIDDEN('@internal/foo')], + }, + { + code: `import { version } from '../../foo/src'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_FORBIDDEN('@internal/foo/src')], + }, + { + code: `import { version } from '../../../package.json'`, + filename: path.join(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ERR_OUTSIDE(path.join(FIXTURE, 'package.json'))], + }, + ], +}); diff --git a/packages/eslint-plugin/src/no-undeclared-imports.test.ts b/packages/eslint-plugin/src/no-undeclared-imports.test.ts new file mode 100644 index 0000000000..1b5cbee853 --- /dev/null +++ b/packages/eslint-plugin/src/no-undeclared-imports.test.ts @@ -0,0 +1,240 @@ +/* + * Copyright 2023 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 { RuleTester } from 'eslint'; +import { join as joinPath } from 'path'; +import rule from '../rules/no-undeclared-imports'; + +const RULE = 'no-undeclared-imports'; +const FIXTURE = joinPath(__dirname, '__fixtures__/monorepo'); + +const ERR_UNDECLARED = ( + name: string, + field: string, + path: string, + flag?: string, +) => ({ + message: `${name} must be declared in ${field} of ${joinPath( + path, + 'package.json', + )}, run 'yarn --cwd ${path} add${ + flag ? ` ${flag}` : '' + } ${name}' from the project root.`, +}); +const ERR_SWITCHED = ( + name: string, + old: string, + field: string, + path: string, +) => ({ + message: `${name} is declared in ${old}, but should be moved to ${field} in ${joinPath( + path, + 'package.json', + )}.`, +}); + +process.chdir(FIXTURE); + +const ruleTester = new RuleTester({ + parserOptions: { + sourceType: 'module', + ecmaVersion: 2021, + }, +}); + +ruleTester.run(RULE, rule, { + valid: [ + { + code: `import '@internal/foo'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import '@internal/bar'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import 'react'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + }, + { + code: `import '@internal/foo'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import '@internal/bar'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + code: `import 'react'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), + }, + { + // We're only able to validate literals + code: `require('lod' + 'ash')`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + }, + ], + invalid: [ + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'lodash', + 'devDependencies', + 'dependencies', + joinPath('packages', 'foo'), + ), + ], + }, + { + code: `import 'react-router'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'react-router', + 'dependencies', + 'peerDependencies', + joinPath('packages', 'bar'), + ), + ], + }, + { + code: `import 'react-router-dom'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_SWITCHED( + 'react-router-dom', + 'devDependencies', + 'peerDependencies', + joinPath('packages', 'bar'), + ), + ], + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import { debounce } from 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import * as _ from 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import _ from 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import('lodash')`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `require('lodash')`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED('lodash', 'dependencies', joinPath('packages', 'bar')), + ], + }, + { + code: `import 'lodash'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.test.ts'), + errors: [ + ERR_UNDECLARED( + 'lodash', + 'devDependencies', + joinPath('packages', 'bar'), + '--dev', + ), + ], + }, + { + code: `import 'react'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.ts'), + errors: [ + ERR_UNDECLARED( + 'react', + 'peerDependencies', + joinPath('packages', 'bar'), + '--peer', + ), + ], + }, + { + code: `import 'react'`, + filename: joinPath(FIXTURE, 'packages/bar/src/index.test.ts'), + errors: [ + ERR_UNDECLARED( + 'react', + 'peerDependencies', + joinPath('packages', 'bar'), + '--peer', + ), + ], + }, + { + code: `import 'react-dom'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.ts'), + errors: [ + ERR_UNDECLARED( + 'react-dom', + 'dependencies', + joinPath('packages', 'foo'), + ), + ], + }, + { + code: `import 'react-dom'`, + filename: joinPath(FIXTURE, 'packages/foo/src/index.test.ts'), + errors: [ + ERR_UNDECLARED( + 'react-dom', + 'devDependencies', + joinPath('packages', 'foo'), + '--dev', + ), + ], + }, + ], +}); diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 27ee4dd712..8813458f86 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/integration-react +## 1.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## 1.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 1.1.9 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index d0eb4e8620..b287f88f87 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": "1.1.9", + "version": "1.1.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 5969521581..2875d54fef 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/repo-tools +## 0.1.2-next.0 + +### Patch Changes + +- ff63acf30a: Packages without a declared `backstage.role` are now ignored. +- Updated dependencies + - @backstage/cli-common@0.1.11 + - @backstage/errors@1.1.4 + ## 0.1.1 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index dd70575433..5ea26060c4 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.1.1", + "version": "0.1.2-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts index b037f40be6..39df70c21a 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -1107,7 +1107,7 @@ export async function categorizePackageDirs(packageDirs: any[]) { }); const role = pkgJson?.backstage?.role; if (!role) { - throw new Error(`No backstage.role in ${dir}/package.json`); + return; // Ignore packages without roles } if (role === 'cli') { cliPackageDirs.push(dir); diff --git a/packages/repo-tools/src/commands/type-deps/type-deps.ts b/packages/repo-tools/src/commands/type-deps/type-deps.ts index d4dd28aa14..4f8e5e5529 100644 --- a/packages/repo-tools/src/commands/type-deps/type-deps.ts +++ b/packages/repo-tools/src/commands/type-deps/type-deps.ts @@ -17,7 +17,7 @@ import fs from 'fs'; import { resolve as resolvePath } from 'path'; // Cba polluting root package.json, we'll have this -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import chalk from 'chalk'; import { getPackages, Package } from '@manypkg/get-packages'; diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 3f00a6a03d..55d39a6ee5 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,43 @@ # techdocs-cli-embedded-app +## 0.2.79-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/app-defaults@1.1.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## 0.2.79-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/app-defaults@1.1.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + ## 0.2.79-next.0 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json b/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json index 2b3a458b95..a467608916 100644 --- a/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json +++ b/packages/techdocs-cli-embedded-app/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 8c3a970cc2..acee2e8cb3 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.79-next.0", + "version": "0.2.79-next.2", "private": true, "backstage": { "role": "frontend" @@ -20,7 +20,7 @@ "@backstage/plugin-techdocs-react": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.11.0", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "history": "^5.0.0", "react": "^17.0.2", diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 4b2566e6e2..54bf7d2e8c 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,27 @@ # @techdocs/cli +## 1.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## 1.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/cli-common@0.1.11 + - @backstage/config@1.0.6 + - @backstage/plugin-techdocs-node@1.4.6-next.1 + ## 1.3.2-next.0 ### Patch Changes diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md index 861dad4605..846ccc88ca 100644 --- a/packages/techdocs-cli/cli-report.md +++ b/packages/techdocs-cli/cli-report.md @@ -33,6 +33,7 @@ Options: --no-docker --techdocs-ref --etag + --site-name -v --verbose --omitTechdocsCoreMkdocsPlugin --legacyCopyReadmeMdToIndexMd @@ -98,6 +99,7 @@ Options: --docker-entrypoint --docker-option --no-docker + --site-name --mkdocs-port -v --verbose --preview-app-bundle-path @@ -115,6 +117,7 @@ Options: --docker-entrypoint --docker-option --no-docker + --site-name -p, --port -v --verbose -h, --help diff --git a/packages/techdocs-cli/cypress.config.js b/packages/techdocs-cli/cypress.config.js new file mode 100644 index 0000000000..abaa324d76 --- /dev/null +++ b/packages/techdocs-cli/cypress.config.js @@ -0,0 +1,30 @@ +/* + * 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 { defineConfig } from 'cypress'; +import { initPlugin } from '@frsource/cypress-plugin-visual-regression-diff/plugins'; + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + initPlugin(on, config); + }, + + excludeSpecPattern: ['**/__snapshots__/*', '**/__image_snapshots__/*'], + }, + viewportWidth: 1920, + viewportHeight: 1080, + includeShadowDom: true, +}); diff --git a/packages/techdocs-cli/cypress.json b/packages/techdocs-cli/cypress.json deleted file mode 100644 index b6f3b96019..0000000000 --- a/packages/techdocs-cli/cypress.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "env": { - "mkDocsBaseUrl": "http://localhost:8000", - "backstageBaseUrl": "http://localhost:3000", - "cypress-plugin-snapshots": { - "autoCleanUp": false, - "imageConfig": { - "resizeDevicePixelRatio": true, - "threshold": 0.01 - } - } - }, - "viewportWidth": 1920, - "viewportHeight": 1080, - "includeShadowDom": true, - "ignoreTestFiles": ["**/__snapshots__/*", "**/__image_snapshots__/*"] -} diff --git a/packages/techdocs-cli/cypress/.eslintrc.json b/packages/techdocs-cli/cypress/.eslintrc.json index 2481ac5715..06965a82da 100644 --- a/packages/techdocs-cli/cypress/.eslintrc.json +++ b/packages/techdocs-cli/cypress/.eslintrc.json @@ -7,15 +7,6 @@ { "assertFunctionNames": ["expect", "cy.contains", "cy.document"] } - ], - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": true, - "optionalDependencies": true, - "peerDependencies": true, - "bundledDependencies": true - } ] } } diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png b/packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png similarity index 100% rename from packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png rename to packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - Backstage Serve toMatchImageSnapshot - Backstage TechDocs Page #0.png diff --git a/packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png b/packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png similarity index 100% rename from packages/techdocs-cli/cypress/integration/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png rename to packages/techdocs-cli/cypress/e2e/__image_snapshots__/TechDocs Live Preview - MkDocs Serve toMatchImageSnapshot - MkDocs Page #0.png diff --git a/packages/techdocs-cli/cypress/integration/backstage_serve.js b/packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js similarity index 94% rename from packages/techdocs-cli/cypress/integration/backstage_serve.js rename to packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js index 15fc03f8f4..0267c8bfe6 100644 --- a/packages/techdocs-cli/cypress/integration/backstage_serve.js +++ b/packages/techdocs-cli/cypress/e2e/backstage_serve.cy.js @@ -48,11 +48,11 @@ describe('TechDocs Live Preview - Backstage Serve', () => { cy.get('.md-footer').should('have.length', 1); }); - it('toMatchImageSnapshot - Backstage TechDocs Page', () => { + it('matchImage - Backstage TechDocs Page', () => { cy.visit( `${Cypress.env('backstageBaseUrl')}/docs/default/component/local`, ).then(() => { - cy.document().toMatchImageSnapshot(); + cy.document().matchImage(); }); }); }); diff --git a/packages/techdocs-cli/cypress/integration/mkdocs_serve.js b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js similarity index 94% rename from packages/techdocs-cli/cypress/integration/mkdocs_serve.js rename to packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js index 1ace7298ce..d9da6caeca 100644 --- a/packages/techdocs-cli/cypress/integration/mkdocs_serve.js +++ b/packages/techdocs-cli/cypress/e2e/mkdocs_serve.cy.js @@ -40,9 +40,9 @@ describe('TechDocs Live Preview - MkDocs Serve', () => { cy.get('.md-footer').should('have.length', 1); }); - it('toMatchImageSnapshot - MkDocs Page', () => { + it('matchImage - MkDocs Page', () => { cy.visit(Cypress.env('mkDocsBaseUrl')).then(() => { - cy.document().toMatchImageSnapshot(); + cy.document().matchImage(); }); }); }); diff --git a/packages/techdocs-cli/cypress/plugins/index.js b/packages/techdocs-cli/cypress/plugins/index.js deleted file mode 100644 index 92faabb6ad..0000000000 --- a/packages/techdocs-cli/cypress/plugins/index.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -const { initPlugin } = require('cypress-plugin-snapshots/plugin'); - -/** - * @type {Cypress.PluginConfig} - */ -// eslint-disable-next-line no-unused-vars -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - initPlugin(on, config); - return config; -}; diff --git a/packages/techdocs-cli/cypress/support/index.js b/packages/techdocs-cli/cypress/support/e2e.js similarity index 94% rename from packages/techdocs-cli/cypress/support/index.js rename to packages/techdocs-cli/cypress/support/e2e.js index a1a5b10ea4..f06a08e9a5 100644 --- a/packages/techdocs-cli/cypress/support/index.js +++ b/packages/techdocs-cli/cypress/support/e2e.js @@ -30,7 +30,7 @@ // Import commands.js using ES2015 syntax: import './commands'; -import 'cypress-plugin-snapshots/commands'; +import '@frsource/cypress-plugin-visual-regression-diff/commands'; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index f60a95840c..092bd687bc 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.3.2-next.0", + "version": "1.3.2-next.2", "publishConfig": { "access": "public" }, @@ -37,6 +37,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@frsource/cypress-plugin-visual-regression-diff": "^3.2.8", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -44,7 +45,6 @@ "@types/serve-handler": "^6.1.0", "@types/webpack-env": "^1.15.3", "cypress": "^10.0.0", - "cypress-plugin-snapshots": "^1.4.4", "find-process": "^1.4.5", "nodemon": "^2.0.2", "techdocs-cli-embedded-app": "link:../techdocs-cli-embedded-app", diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 874b904d86..8445dd9ec6 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -21,6 +21,7 @@ import Docker from 'dockerode'; import { TechdocsGenerator, ParsedLocationAnnotation, + getMkDocsYml, } from '@backstage/plugin-techdocs-node'; import { ContainerRunner, @@ -54,6 +55,10 @@ export default async function generate(opts: OptionValues) { await fs.ensureDir(outputDir); + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + sourceDir, + ); + const config = new ConfigReader({ techdocs: { generator: { @@ -106,7 +111,14 @@ export default async function generate(opts: OptionValues) { logger, etag: opts.etag, ...(process.env.LOG_LEVEL === 'debug' ? { logStream: stdout } : {}), + siteOptions: { name: opts.siteName }, }); + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } + logger.info('Done!'); } diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index caa7d8efbd..102e6d87de 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -54,6 +54,11 @@ export function registerCommands(program: Command) { '--etag ', 'A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored in techdocs_metadata.json.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Documentation Site', + ) .option('-v --verbose', 'Enable verbose output.', false) .option( '--omitTechdocsCoreMkdocsPlugin', @@ -224,6 +229,11 @@ export function registerCommands(program: Command) { '--no-docker', 'Do not use Docker, run `mkdocs serve` in current user environment.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Documentation Site', + ) .option('-p, --port ', 'Port to serve documentation locally', '8000') .option('-v --verbose', 'Enable verbose output.', false) .action(lazy(() => import('./serve/mkdocs').then(m => m.default))); @@ -250,6 +260,11 @@ export function registerCommands(program: Command) { '--no-docker', 'Do not use Docker, use MkDocs executable in current user environment.', ) + .option( + '--site-name', + 'Name for site when using default MkDocs config', + 'Documentation Site', + ) .option('--mkdocs-port ', 'Port for MkDocs server to use', '8000') .option('-v --verbose', 'Enable verbose output.', false) .option( diff --git a/packages/techdocs-cli/src/commands/serve/mkdocs.ts b/packages/techdocs-cli/src/commands/serve/mkdocs.ts index 9cc0aef3be..1a471cf1a6 100644 --- a/packages/techdocs-cli/src/commands/serve/mkdocs.ts +++ b/packages/techdocs-cli/src/commands/serve/mkdocs.ts @@ -19,6 +19,8 @@ import openBrowser from 'react-dev-utils/openBrowser'; import { createLogger } from '../../lib/utility'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; +import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import fs from 'fs-extra'; export default async function serveMkdocs(opts: OptionValues) { const logger = createLogger({ verbose: opts.verbose }); @@ -26,6 +28,12 @@ export default async function serveMkdocs(opts: OptionValues) { const dockerAddr = `http://0.0.0.0:${opts.port}`; const localAddr = `http://127.0.0.1:${opts.port}`; const expectedDevAddr = opts.docker ? dockerAddr : localAddr; + + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + './', + opts.siteName, + ); + // We want to open browser only once based on a log. let boolOpenBrowserTriggered = false; @@ -70,4 +78,10 @@ export default async function serveMkdocs(opts: OptionValues) { // Keep waiting for user to cancel the process await waitForSignal([childProcess]); + + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } } diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index d46c70678a..48e48d4f66 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -22,6 +22,8 @@ import HTTPServer from '../../lib/httpServer'; import { runMkdocsServer } from '../../lib/mkdocsServer'; import { LogFunc, waitForSignal } from '../../lib/run'; import { createLogger } from '../../lib/utility'; +import { getMkDocsYml } from '@backstage/plugin-techdocs-node'; +import fs from 'fs-extra'; function findPreviewBundlePath(): string { try { @@ -64,6 +66,11 @@ export default async function serve(opts: OptionValues) { ? mkdocsDockerAddr : mkdocsLocalAddr; + const { path: mkDocsYmlPath, configIsTemporary } = await getMkDocsYml( + './', + opts.siteName, + ); + let mkdocsServerHasStarted = false; const mkdocsLogFunc: LogFunc = data => { // Sometimes the lines contain an unnecessary extra new line @@ -140,4 +147,10 @@ export default async function serve(opts: OptionValues) { }); await waitForSignal([mkdocsChildProcess]); + + if (configIsTemporary) { + process.on('exit', async () => { + fs.rmSync(mkDocsYmlPath, {}); + }); + } } diff --git a/packages/techdocs-cli/src/lib/PublisherConfig.ts b/packages/techdocs-cli/src/lib/PublisherConfig.ts index 0d1c8fc8a9..0ef6b66eaf 100644 --- a/packages/techdocs-cli/src/lib/PublisherConfig.ts +++ b/packages/techdocs-cli/src/lib/PublisherConfig.ts @@ -17,7 +17,7 @@ import { ConfigReader } from '@backstage/config'; import { OptionValues } from 'commander'; -type Publisher = keyof typeof PublisherConfig['configFactories']; +type Publisher = keyof (typeof PublisherConfig)['configFactories']; type PublisherConfiguration = { [p in Publisher]?: any; } & { @@ -73,7 +73,7 @@ export class PublisherConfig { */ private static isKnownPublisher( type: string, - ): type is keyof typeof PublisherConfig['configFactories'] { + ): type is keyof (typeof PublisherConfig)['configFactories'] { return PublisherConfig.configFactories.hasOwnProperty(type); } diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 5738586f5c..72ef042554 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + ## 1.2.4 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index c3f9349390..396bbcc4ed 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.2.4", + "version": "1.2.5-next.0", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/test-utils/src/testUtils/TestApiProvider.tsx b/packages/test-utils/src/testUtils/TestApiProvider.tsx index 51edf77cba..35fa302415 100644 --- a/packages/test-utils/src/testUtils/TestApiProvider.tsx +++ b/packages/test-utils/src/testUtils/TestApiProvider.tsx @@ -119,7 +119,7 @@ export class TestApiRegistry implements ApiHolder { * implements a subset of the `IdentityApi`. * * @public - **/ + */ export const TestApiProvider = ( props: TestApiProviderProps, ) => { diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index 5e222c0c3e..53f3a3ef2b 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -159,7 +159,7 @@ export function createThemeOverrides(theme: BackstageTheme): Overrides { head: { wordBreak: 'break-word', overflow: 'hidden', - color: 'rgb(179, 179, 179)', + color: theme.palette.textSubtle, fontWeight: 'normal', lineHeight: '1', }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index c03478eb10..11f11a19b9 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-adr-backend +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-search-common@1.2.1 + +## 0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-adr-common@0.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.7-next.0 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 17b91e62ef..33679a00dc 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.2.7-next.0", + "version": "0.2.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-backend/src/service/router.test.ts b/plugins/adr-backend/src/service/router.test.ts index fbbd6e8532..f12b29c70a 100644 --- a/plugins/adr-backend/src/service/router.test.ts +++ b/plugins/adr-backend/src/service/router.test.ts @@ -107,6 +107,8 @@ class MockCacheClient implements CacheClient { async delete(key: string) { delete this.itemRegistry[key]; } + + withOptions = () => this; } describe('createRouter', () => { diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 4ee9e2fd8e..7ed77717a1 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-adr-common +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/integration@1.4.2 + - @backstage/plugin-search-common@1.2.1 + ## 0.2.6-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index a34cf5497c..7bae7294bb 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.6-next.0", + "version": "0.2.6-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index a1a9592ace..cea1b59deb 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-adr +## 0.4.0-next.2 + +### Minor Changes + +- ec34b535c0: The `AdrSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- ec34b535c0: Support displaying an icon on `AdrSearchResultListItem` +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-adr-common@0.2.6-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 0.3.1-next.0 ### Patch Changes diff --git a/plugins/adr/api-report.md b/plugins/adr/api-report.md index d6480cd090..4ced4e9416 100644 --- a/plugins/adr/api-report.md +++ b/plugins/adr/api-report.md @@ -11,6 +11,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { isAdrAvailable } from '@backstage/plugin-adr-common'; +import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -82,12 +83,18 @@ export type AdrReadResult = { }; // @public -export function AdrSearchResultListItem(props: { +export const AdrSearchResultListItem: ( + props: AdrSearchResultListItemProps, +) => JSX.Element | null; + +// @public (undocumented) +export type AdrSearchResultListItemProps = { lineClamp?: number; highlight?: ResultHighlight; + icon?: ReactNode; rank?: number; - result: AdrDocument; -}): JSX.Element; + result?: AdrDocument; +}; // @public export const EntityAdrContent: (props: { diff --git a/plugins/adr/package.json b/plugins/adr/package.json index e8e7de06e6..085729f86f 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.3.1-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,6 +39,7 @@ "remark-gfm": "^3.0.1" }, "peerDependencies": { + "@types/react": "^16.13.1 || ^17.0.0", "react": "^16.13.1 || ^17.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, diff --git a/plugins/adr/src/index.ts b/plugins/adr/src/index.ts index 2ec76b0fd6..f24b3ac531 100644 --- a/plugins/adr/src/index.ts +++ b/plugins/adr/src/index.ts @@ -30,5 +30,5 @@ export type { } from './api'; export { isAdrAvailable } from '@backstage/plugin-adr-common'; export * from './components/AdrReader'; -export { adrPlugin, EntityAdrContent } from './plugin'; -export * from './search'; +export { adrPlugin, AdrSearchResultListItem, EntityAdrContent } from './plugin'; +export type { AdrSearchResultListItemProps } from './search'; diff --git a/plugins/adr/src/plugin.ts b/plugins/adr/src/plugin.ts index f23df826cd..05e4adec4a 100644 --- a/plugins/adr/src/plugin.ts +++ b/plugins/adr/src/plugin.ts @@ -21,7 +21,9 @@ import { createRoutableExtension, discoveryApiRef, } from '@backstage/core-plugin-api'; +import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; import { rootRouteRef } from './routes'; +import { AdrSearchResultListItemProps } from './search'; /** * The Backstage plugin that holds ADR specific components @@ -57,3 +59,21 @@ export const EntityAdrContent = adrPlugin.provide( mountPoint: rootRouteRef, }), ); + +/** + * React extension used to render results on Search page or modal + * + * @public + */ +export const AdrSearchResultListItem: ( + props: AdrSearchResultListItemProps, +) => JSX.Element | null = adrPlugin.provide( + createSearchResultListItemExtension({ + name: 'AdrSearchResultListItem', + component: () => + import('./search/AdrSearchResultListItem').then( + m => m.AdrSearchResultListItem, + ), + predicate: result => result.type === 'adr', + }), +); diff --git a/plugins/adr/src/search/AdrSearchResultListItem.tsx b/plugins/adr/src/search/AdrSearchResultListItem.tsx index 3a11b5cf9a..118333a439 100644 --- a/plugins/adr/src/search/AdrSearchResultListItem.tsx +++ b/plugins/adr/src/search/AdrSearchResultListItem.tsx @@ -14,19 +14,19 @@ * limitations under the License. */ -import React from 'react'; +import React, { ReactNode } from 'react'; import { Box, Chip, Divider, ListItem, + ListItemIcon, ListItemText, makeStyles, } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { parseEntityRef } from '@backstage/catalog-model'; import { Link } from '@backstage/core-components'; -import { useAnalytics } from '@backstage/core-plugin-api'; import { AdrDocument } from '@backstage/plugin-adr-common'; import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; import { ResultHighlight } from '@backstage/plugin-search-common'; @@ -43,35 +43,36 @@ const useStyles = makeStyles({ }, }); +/** + * @public + */ +export type AdrSearchResultListItemProps = { + lineClamp?: number; + highlight?: ResultHighlight; + icon?: ReactNode; + rank?: number; + result?: AdrDocument; +}; + /** * A component to display an ADR search result. * @public */ -export function AdrSearchResultListItem(props: { - lineClamp?: number; - highlight?: ResultHighlight; - rank?: number; - result: AdrDocument; -}) { - const { lineClamp = 5, highlight, rank, result } = props; +export function AdrSearchResultListItem(props: AdrSearchResultListItemProps) { + const { lineClamp = 5, highlight, icon, result } = props; const classes = useStyles(); - const analytics = useAnalytics(); - const handleClick = () => { - analytics.captureEvent('discover', result.title, { - attributes: { to: result.location }, - value: rank, - }); - }; + if (!result) return null; return ( <> + {icon && {icon}} + {highlight?.fields.title ? ( JSX.Element; + +// @public (undocumented) +export const TrpcApiDefinitionWidget: ( + props: TrpcApiDefinitionWidgetProps, +) => JSX.Element; + +// @public (undocumented) +export type TrpcApiDefinitionWidgetProps = { + definition: string; +}; ``` diff --git a/plugins/api-docs/dev/index.tsx b/plugins/api-docs/dev/index.tsx index 9975e91e98..995aa9c2fb 100644 --- a/plugins/api-docs/dev/index.tsx +++ b/plugins/api-docs/dev/index.tsx @@ -32,6 +32,7 @@ import graphqlApiEntity from './graphql-example-api.yaml'; import invalidLanguageApiEntity from './invalid-language-example-api.yaml'; import openapiApiEntity from './openapi-example-api.yaml'; import otherApiEntity from './other-example-api.yaml'; +import trpcApiEntity from './trpc-example-api.yaml'; const mockEntities = [ openapiApiEntity, @@ -39,6 +40,7 @@ const mockEntities = [ graphqlApiEntity, invalidLanguageApiEntity, otherApiEntity, + trpcApiEntity, ] as unknown as Entity[]; createDevApp() @@ -137,4 +139,17 @@ createDevApp() ), }) + .addPage({ + title: 'tRPC', + element: ( + +
    + + + + + + + ), + }) .render(); diff --git a/plugins/api-docs/dev/trpc-example-api.yaml b/plugins/api-docs/dev/trpc-example-api.yaml new file mode 100644 index 0000000000..f5807537b3 --- /dev/null +++ b/plugins/api-docs/dev/trpc-example-api.yaml @@ -0,0 +1,25 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world-trpc + description: Hello World example for tRPC +spec: + type: trpc + lifecycle: experimental + owner: team-c + definition: | + import { z } from 'zod'; + import { publicProcedure, router } from '../trpc'; + + export const apiRouter = router({ + version: publicProcedure.query(() => { + return { version: '0.42.0' }; + }), + hello: publicProcedure + .input(z.object({ username: z.string().nullish() }).nullish()) + .query(({ input, ctx }) => { + return { + text: `hello ${input?.username ?? ctx.user?.name ?? 'world'}`, + }; + }), + }); diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index a7ad050db1..ee3e88fe11 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.8.15-next.0", + "version": "0.9.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@asyncapi/react-component": "1.0.0-next.44", + "@asyncapi/react-component": "1.0.0-next.47", "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx index 03a56eaa78..8d7d7a7729 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionWidget.tsx @@ -18,6 +18,7 @@ import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget'; import { GraphQlDefinitionWidget } from '../GraphQlDefinitionWidget'; import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget'; import { GrpcApiDefinitionWidget } from '../GrpcApiDefinitionWidget'; +import { TrpcApiDefinitionWidget } from '../TrpcDefinitionWidget'; /** @public */ export type ApiDefinitionWidget = { @@ -61,5 +62,12 @@ export function defaultDefinitionWidgets(): ApiDefinitionWidget[] { ), }, + { + type: 'trpc', + title: 'tRPC', + component: definition => ( + + ), + }, ]; } diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx new file mode 100644 index 0000000000..d7e6951e2e --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.test.tsx @@ -0,0 +1,32 @@ +/* + * 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 { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { TrpcApiDefinitionWidget } from './TrpcApiDefinitionWidget'; + +describe('', () => { + it('renders plain text', async () => { + const { getAllByText } = await renderInTestApp( + , + ); + + expect( + getAllByText((_text, element) => element?.textContent === 'Hello World') + .length, + ).toBeGreaterThan(0); + }); +}); diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx new file mode 100644 index 0000000000..af73335dbd --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/TrpcApiDefinitionWidget.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { CodeSnippet } from '@backstage/core-components'; +import { useTheme } from '@material-ui/core/styles'; +import { BackstageTheme } from '@backstage/theme'; + +/** @public */ +export type TrpcApiDefinitionWidgetProps = { + definition: string; +}; + +/** @public */ +export const TrpcApiDefinitionWidget = ( + props: TrpcApiDefinitionWidgetProps, +) => { + const { definition } = props; + const theme = useTheme(); + return ( + + ); +}; diff --git a/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts b/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts new file mode 100644 index 0000000000..604adb06f3 --- /dev/null +++ b/plugins/api-docs/src/components/TrpcDefinitionWidget/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 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 { + TrpcApiDefinitionWidget, + type TrpcApiDefinitionWidgetProps, +} from './TrpcApiDefinitionWidget'; diff --git a/plugins/api-docs/src/components/index.ts b/plugins/api-docs/src/components/index.ts index ea40076af4..7e7b206c54 100644 --- a/plugins/api-docs/src/components/index.ts +++ b/plugins/api-docs/src/components/index.ts @@ -22,3 +22,4 @@ export * from './ComponentsCards'; export * from './GraphQlDefinitionWidget'; export * from './OpenApiDefinitionWidget'; export * from './PlainApiDefinitionWidget'; +export * from './TrpcDefinitionWidget'; diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index a123d9c7ed..8903d504a9 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-apollo-explorer +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.1.8-next.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.7 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 60fbb7fa7b..7917f5a417 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.7", + "version": "0.1.8-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,7 +26,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@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", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 92b5e137fd..617d74217b 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-app-backend +## 0.3.42-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + +## 0.3.42-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/config-loader@1.1.8 + - @backstage/types@1.0.2 + ## 0.3.42-next.0 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index a2c631be3c..ff9cd8fe5f 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.42-next.0", + "version": "0.3.42-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts index b12a8d6877..a29f8fd5a8 100644 --- a/plugins/app-backend/src/service/appPlugin.ts +++ b/plugins/app-backend/src/service/appPlugin.ts @@ -71,7 +71,7 @@ export type AppPluginOptions = { * @alpha */ export const appPlugin = createBackendPlugin((options: AppPluginOptions) => ({ - id: 'app', + pluginId: 'app', register(env) { env.registerInit({ deps: { diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index cd39dba0f5..f76848cb94 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-auth-backend +## 0.17.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## 0.17.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 0.17.5-next.0 ### Patch Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 88cb33863e..f6b19189cd 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -7,7 +7,7 @@ import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; import { BackstageSignInResult } from '@backstage/plugin-auth-node'; -import { CacheClient } from '@backstage/backend-plugin-api'; +import { CacheService } from '@backstage/backend-plugin-api'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; @@ -486,7 +486,7 @@ export const providers: Readonly<{ signIn: { resolver: SignInResolver; }; - cache?: CacheClient | undefined; + cache?: CacheService | undefined; }) => AuthProviderFactory; resolvers: Readonly<{ emailMatchingUserEntityProfileEmail: () => SignInResolver; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 1b47bd6ba5..7a855e62a8 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.17.5-next.0", + "version": "0.17.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts index 6653bc38cb..1abca4bdf4 100644 --- a/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts +++ b/plugins/auth-backend/src/providers/cloudflare-access/provider.test.ts @@ -83,6 +83,7 @@ const mockCacheClient = { get: jest.fn(), set: jest.fn(), delete: jest.fn(), + withOptions: jest.fn(), }; jest.mock('jose'); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index c675d75b0f..7f9e0f8a33 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-node +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.11-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 5b1c29c7d7..fe7adb300d 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.11-next.0", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index 7cfd680a24..7488628b80 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.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + +## 0.3.21-next.1 + +### Patch Changes + +- cc926a59bd: Fixed a bug where the azure devops host in URLs on the readme card was being URL encoded, breaking hosts with ports. +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.3.21-next.0 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 4960d8e56a..2103acf8fc 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.21-next.0", + "version": "0.3.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index 1a0d559ab1..cb4be6f908 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-azure-devops +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-devops-common@0.3.0 + ## 0.2.6-next.0 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 87c9521443..bfb09aff1d 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.6-next.0", + "version": "0.2.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index be020f508b..e3680abddb 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-azure-sites-backend +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index 829ed89f6a..c053435161 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 0b7ea2a680..8c44d24ff3 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-azure-sites +## 0.1.4-next.2 + +### Patch Changes + +- 98a00a09d5: Fixed `AzureSites` plugin start and stop issue #15904 + Fixed `AzureSites` UI load issue #15907 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-azure-sites-common@0.1.0 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index b636065426..3cfe1ea9c3 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts b/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts index fc622e786b..b66a3cbb3f 100644 --- a/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts +++ b/plugins/azure-sites/src/api/AzureSitesApiBackendClient.ts @@ -35,7 +35,7 @@ export class AzureSitesApiBackendClient implements AzureSitesApi { } async stop(request: AzureSiteStartStopRequest): Promise { - const url = `${await this.discoveryApi.getBaseUrl('azure-functions')}/${ + const url = `${await this.discoveryApi.getBaseUrl('azure-sites')}/${ request.subscription }/${request.resourceGroup}/${request.name}/stop`; const { token: accessToken } = await this.identityApi.getCredentials(); @@ -48,7 +48,7 @@ export class AzureSitesApiBackendClient implements AzureSitesApi { }); } async start(request: AzureSiteStartStopRequest): Promise { - const url = `${await this.discoveryApi.getBaseUrl('azure-functions')}/${ + const url = `${await this.discoveryApi.getBaseUrl('azure-sites')}/${ request.subscription }/${request.resourceGroup}/${request.name}/start`; const { token: accessToken } = await this.identityApi.getCredentials(); diff --git a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx index a25d186a48..dc059b2f15 100644 --- a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx +++ b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx @@ -73,9 +73,11 @@ const Kind = ({ value }: { value: Kinds }) => { app: , functionapp: , }; + const kindArray = value.split(','); + const iconValue: Kinds = kindArray.includes('app') ? 'app' : 'functionapp'; return ( - {iconMap[value]} + {iconMap[iconValue]} ); }; diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 1a703ba72f..ca5bbb859d 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-badges-backend +## 0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.1.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.36-next.0 ### Patch Changes diff --git a/plugins/badges-backend/api-report.md b/plugins/badges-backend/api-report.md index 0ecf41ee85..8ca4b561a2 100644 --- a/plugins/badges-backend/api-report.md +++ b/plugins/badges-backend/api-report.md @@ -79,7 +79,7 @@ export type BadgeSpec = { }; // @public (undocumented) -export type BadgeStyle = typeof BADGE_STYLES[number]; +export type BadgeStyle = (typeof BADGE_STYLES)[number]; // @public (undocumented) export const createDefaultBadgeFactories: () => BadgeFactories; diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index bcc39f4c96..25beed0238 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.36-next.0", + "version": "0.1.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/src/types.ts b/plugins/badges-backend/src/types.ts index eec7063f88..0d778289f9 100644 --- a/plugins/badges-backend/src/types.ts +++ b/plugins/badges-backend/src/types.ts @@ -27,7 +27,7 @@ export const BADGE_STYLES = [ ] as const; /** @public */ -export type BadgeStyle = typeof BADGE_STYLES[number]; +export type BadgeStyle = (typeof BADGE_STYLES)[number]; /** @public */ export interface Badge { diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 0ee582ecea..cefd2f8ccd 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-badges +## 0.2.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.39-next.0 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 717224216d..4c8edbd09f 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.39-next.0", + "version": "0.2.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 6c98a2125d..5a7107312e 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-bazaar-backend +## 0.2.5-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/api-report.md b/plugins/bazaar-backend/api-report.md index 1ee889c04a..6281530851 100644 --- a/plugins/bazaar-backend/api-report.md +++ b/plugins/bazaar-backend/api-report.md @@ -3,12 +3,16 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; +// @alpha +export const bazaarPlugin: () => BackendFeature; + // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index fe9893dbbb..5fba3fcbb3 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,20 +1,21 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.2.5-next.0", + "version": "0.2.5-next.2", "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" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -23,7 +24,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -35,10 +36,12 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" }, "files": [ "dist", - "migrations/**/*.{js,d.ts}" + "migrations/**/*.{js,d.ts}", + "alpha" ] } diff --git a/plugins/bazaar-backend/src/index.ts b/plugins/bazaar-backend/src/index.ts index ca73cb27ba..dd0cdbb750 100644 --- a/plugins/bazaar-backend/src/index.ts +++ b/plugins/bazaar-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { bazaarPlugin } from './plugin'; diff --git a/plugins/bazaar-backend/src/plugin.ts b/plugins/bazaar-backend/src/plugin.ts new file mode 100644 index 0000000000..62622717c8 --- /dev/null +++ b/plugins/bazaar-backend/src/plugin.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Bazaar backend plugin. + * + * @alpha + */ +export const bazaarPlugin = createBackendPlugin({ + pluginId: 'bazaar', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + database: coreServices.database, + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ database, config, identity, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + database, + config, + identity, + logger: loggerToWinstonLogger(logger), + }), + ); + }, + }); + }, +}); diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index aab91930cb..d3b9cc6a71 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-bazaar +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.1 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.22.2-next.0 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.4-next.0 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index c949415d13..7558aaf2ec 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.4-next.0", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitbucket-cloud-common/api-report.md b/plugins/bitbucket-cloud-common/api-report.md index 5182579a4b..95e6f36836 100644 --- a/plugins/bitbucket-cloud-common/api-report.md +++ b/plugins/bitbucket-cloud-common/api-report.md @@ -132,7 +132,7 @@ export namespace Models { readonly Plaintext: 'plaintext'; }; export type BaseCommitSummaryMarkupEnum = - typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; + (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; export interface Branch { default_merge_strategy?: string; // (undocumented) @@ -150,7 +150,7 @@ export namespace Models { readonly FastForward: 'fast_forward'; }; export type BranchMergeStrategiesEnum = - typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; + (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; export interface Commit extends BaseCommit { // (undocumented) participants?: Array; @@ -179,7 +179,7 @@ export namespace Models { }; // (undocumented) export type CommitFileAttributesEnum = - typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; + (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; export interface Link { // (undocumented) href?: string; @@ -221,7 +221,7 @@ export namespace Models { }; // (undocumented) export type ParticipantRoleEnum = - typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; + (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; const // (undocumented) ParticipantStateEnum: { readonly Approved: 'approved'; @@ -230,7 +230,7 @@ export namespace Models { }; // (undocumented) export type ParticipantStateEnum = - typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; + (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; export interface Project extends ModelObject { // (undocumented) created_on?: string; @@ -306,7 +306,7 @@ export namespace Models { readonly NoForks: 'no_forks'; }; export type RepositoryForkPolicyEnum = - typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; + (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; const // (undocumented) RepositoryScmEnum: { readonly Git: 'git'; @@ -336,7 +336,7 @@ export namespace Models { } // (undocumented) export type RepositoryScmEnum = - typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; + (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; // (undocumented) export interface SearchCodeSearchResult { // (undocumented) diff --git a/plugins/bitbucket-cloud-common/src/models/index.ts b/plugins/bitbucket-cloud-common/src/models/index.ts index 9d25bbb873..d868e2926c 100644 --- a/plugins/bitbucket-cloud-common/src/models/index.ts +++ b/plugins/bitbucket-cloud-common/src/models/index.ts @@ -107,7 +107,7 @@ export namespace Models { * @public */ export type BaseCommitSummaryMarkupEnum = - typeof BaseCommitSummaryMarkupEnum[keyof typeof BaseCommitSummaryMarkupEnum]; + (typeof BaseCommitSummaryMarkupEnum)[keyof typeof BaseCommitSummaryMarkupEnum]; /** * A branch object, representing a branch in a repository. @@ -146,7 +146,7 @@ export namespace Models { * @public */ export type BranchMergeStrategiesEnum = - typeof BranchMergeStrategiesEnum[keyof typeof BranchMergeStrategiesEnum]; + (typeof BranchMergeStrategiesEnum)[keyof typeof BranchMergeStrategiesEnum]; /** * A repository commit object. @@ -191,7 +191,7 @@ export namespace Models { * @public */ export type CommitFileAttributesEnum = - typeof CommitFileAttributesEnum[keyof typeof CommitFileAttributesEnum]; + (typeof CommitFileAttributesEnum)[keyof typeof CommitFileAttributesEnum]; /** * A link to a resource related to this object. @@ -280,7 +280,7 @@ export namespace Models { * @public */ export type ParticipantRoleEnum = - typeof ParticipantRoleEnum[keyof typeof ParticipantRoleEnum]; + (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum]; /** * @public @@ -295,7 +295,7 @@ export namespace Models { * @public */ export type ParticipantStateEnum = - typeof ParticipantStateEnum[keyof typeof ParticipantStateEnum]; + (typeof ParticipantStateEnum)[keyof typeof ParticipantStateEnum]; /** * A Bitbucket project. @@ -423,7 +423,7 @@ export namespace Models { * @public */ export type RepositoryForkPolicyEnum = - typeof RepositoryForkPolicyEnum[keyof typeof RepositoryForkPolicyEnum]; + (typeof RepositoryForkPolicyEnum)[keyof typeof RepositoryForkPolicyEnum]; /** * @public @@ -436,7 +436,7 @@ export namespace Models { * @public */ export type RepositoryScmEnum = - typeof RepositoryScmEnum[keyof typeof RepositoryScmEnum]; + (typeof RepositoryScmEnum)[keyof typeof RepositoryScmEnum]; /** * @public diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index a41c9ed630..65cef85765 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-bitrise +## 0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.42-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.42-next.0 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index cf3515aa89..13cc29fd06 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.42-next.0", + "version": "0.1.42-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 39c217fc58..d0eeb5702c 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index 63b85f223b..1725692cb1 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -11,7 +11,7 @@ import { Config } from '@backstage/config'; import { Credentials } from 'aws-sdk'; import { EntityProvider } from '@backstage/plugin-catalog-backend'; import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; -import { LocationSpec } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { Logger } from 'winston'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { TaskRunner } from '@backstage/backend-tasks'; diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 4ccc463937..0c9d9af8bb 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.15-next.0", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts index 87b7f2c487..ecf3b1a961 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.test.ts @@ -20,10 +20,12 @@ import aws from 'aws-sdk'; describe('AwsEKSClusterProcessor', () => { AWSMock.setSDKInstance(aws); + describe('readLocation', () => { const processor = new (AwsEKSClusterProcessor as any)({}); const location = { type: 'aws-eks', target: '957140518395/us-west-2' }; const emit = jest.fn(); + it('generates cluster correctly', async () => { const clusters: aws.EKS.Types.ListClustersResponse = { clusters: ['backstage-test'], @@ -40,11 +42,12 @@ describe('AwsEKSClusterProcessor', () => { }, }, }; - AWSMock.mock('EKS', 'listClusters', clusters); + AWSMock.mock('EKS', 'listClusters', clusters); AWSMock.mock('EKS', 'describeCluster', cluster); await processor.readLocation(location, false, emit); + expect(emit).toHaveBeenCalledWith({ type: 'entity', location, diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts index c34b247f4d..b6418ade03 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { CatalogProcessor, CatalogProcessorEmit, - LocationSpec, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { ANNOTATION_KUBERNETES_API_SERVER, ANNOTATION_KUBERNETES_API_SERVER_CA, ANNOTATION_KUBERNETES_AUTH_PROVIDER, -} from '@backstage/catalog-model'; +} from '@backstage/plugin-kubernetes-common'; import { Credentials, EKS } from 'aws-sdk'; import { AWSCredentialFactory } from '../types'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts index 1018e49a41..ecc42e69ea 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsOrganizationCloudAccountProcessor.ts @@ -19,9 +19,9 @@ import { Config } from '@backstage/config'; import { CatalogProcessor, CatalogProcessorEmit, - LocationSpec, processingResult, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import AWS, { Credentials, Organizations } from 'aws-sdk'; import { Account, ListAccountsResponse } from 'aws-sdk/clients/organizations'; import { Logger } from 'winston'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts index 84f2289c94..072c3d8384 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsS3DiscoveryProcessor.ts @@ -20,9 +20,9 @@ import { CatalogProcessor, CatalogProcessorEmit, CatalogProcessorParser, - LocationSpec, processingResult, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import limiterFactory from 'p-limit'; /** diff --git a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts index b92fcfc022..5e24d4dc13 100644 --- a/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/providers/AwsS3EntityProvider.ts @@ -20,9 +20,9 @@ import { AwsS3Integration, ScmIntegrations } from '@backstage/integration'; import { EntityProvider, EntityProviderConnection, - LocationSpec, locationSpecToLocationEntity, } from '@backstage/plugin-catalog-backend'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { AwsCredentials } from '../credentials/AwsCredentials'; import { readAwsS3Configs } from './config'; import { AwsS3Config } from './types'; diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 33d4ea499c..05e48690d7 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,65 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.1.13-next.1 + +### Patch Changes + +- 2890f47517: This will add the ability to use Azure DevOps with multi project with a single value which is a new feature as previously this had to be done manually for each project that you wanted to add. + + Right now you would have to fill in multiple values in the config to use multiple projects: + + ``` + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'firstProject' # this will match the firstProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + yourSecondProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: 'secondProject' # this will match the secondProject project + repository: '*' # this will match all repos + path: /catalog-info.yaml + ``` + + With this change you can actually have all projects available where your PAT determines which you have access to, so that includes multiple projects: + + ``` + yourFirstProviderId: # identifies your dataset / provider independent of config changes + organization: myorg + project: '*' # this will match all projects where your PAT has access to + repository: '*' # this will match all repos + path: /catalog-info.yaml + ``` + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 366a4e05ee..9552fe1e98 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.13-next.0", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts index 4852edbb03..8893d5d42d 100644 --- a/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-azure/src/processors/AzureDevOpsDiscoveryProcessor.ts @@ -43,7 +43,7 @@ import { codeSearch } from '../lib'; * target: https://dev.azure.com/org/project/_git/repo * * @public - **/ + */ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; @@ -123,7 +123,7 @@ export class AzureDevOpsDiscoveryProcessor implements CatalogProcessor { /** * parseUrl extracts segments from the Azure DevOps URL. - **/ + */ export function parseUrl(urlString: string): { baseUrl: string; org: string; diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 71a876e98a..261a192dfa 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 9b1c18ddb2..78e1e15653 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.9-next.0", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 1290c701b6..b3b825bbc6 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index b9b1eff3d4..edd1fbf0e6 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.7-next.0", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 390601b255..b07c7a92bb 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + +## 0.2.9-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-bitbucket-cloud-common@0.2.3 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index e5bb59e93d..7df64bbc87 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.9-next.0", + "version": "0.2.9-next.2", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 80723a0f97..9efd73aac5 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.10-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 0ab3e69749..4e8d389c9c 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.10-next.0", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index d8d457c0c4..089cd237e2 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-backend-module-github +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## 0.2.5-next.1 + +### Patch Changes + +- 66158754b4: Add support for filtering out forks +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index ae485f101f..36cd96274a 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.2.5-next.0", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/src/lib/annotation.ts b/plugins/catalog-backend-module-github/src/lib/annotation.ts new file mode 100644 index 0000000000..3b2f7b87a8 --- /dev/null +++ b/plugins/catalog-backend-module-github/src/lib/annotation.ts @@ -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. + */ + +/** + * The value of this annotation is the so-called login that identifies a user on +[GitHub](https://github.com) (either the public one, or a private GitHub +Enterprise installation) that is related to this entity. It is on the format +``, and is the same as can be seen in the URL location bar of the +browser when viewing that user. + * + * @public + */ +export const ANNOTATION_GITHUB_USER_LOGIN = 'github.com/user-login'; + +/** + * The value of this annotation is the so-called slug that identifies a team on +[GitHub](https://github.com) (either the public one, or a private GitHub +Enterprise installation) that is related to this entity. It is on the format +`/`, and is the same as can be seen in the URL location bar +of the browser when viewing that team. + * + * @public + */ +export const ANNOTATION_GITHUB_TEAM_SLUG = 'github.com/team-slug'; diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index efd3eedd5d..7669fd5b47 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -16,6 +16,10 @@ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; import { graphql } from '@octokit/graphql'; +import { + ANNOTATION_GITHUB_TEAM_SLUG, + ANNOTATION_GITHUB_USER_LOGIN, +} from './annotation'; import { GithubTeam, GithubUser } from './github'; /** @@ -63,7 +67,7 @@ export const defaultUserTransformer: UserTransformer = async ( metadata: { name: item.login, annotations: { - 'github.com/user-login': item.login, + [ANNOTATION_GITHUB_USER_LOGIN]: item.login, }, }, spec: { @@ -87,7 +91,7 @@ export const defaultUserTransformer: UserTransformer = async ( export const defaultOrganizationTeamTransformer: TeamTransformer = async team => { const annotations: { [annotationName: string]: string } = { - 'github.com/team-slug': team.combinedSlug, + [ANNOTATION_GITHUB_TEAM_SLUG]: team.combinedSlug, }; if (team.editTeamUrl) { diff --git a/plugins/catalog-backend-module-github/src/lib/util.ts b/plugins/catalog-backend-module-github/src/lib/util.ts index d284fdabde..54ee575a6c 100644 --- a/plugins/catalog-backend-module-github/src/lib/util.ts +++ b/plugins/catalog-backend-module-github/src/lib/util.ts @@ -88,3 +88,14 @@ export function satisfiesForkFilter( // if forks are allowed, allow all repos through return true; } + +// Given the github organisation team slug, returns a tuple containing [organisation, team] +export function splitTeamSlug(slug: string): [string, string] { + const parts = slug.split('/'); + if (parts.length !== 2) { + throw new Error( + `Github team slug '${slug}' was not in the expected format /`, + ); + } + return [parts[0], parts[1]]; +} diff --git a/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts b/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts index 3fec87d0b2..c6733df13b 100644 --- a/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts +++ b/plugins/catalog-backend-module-github/src/processors/GithubDiscoveryProcessor.ts @@ -46,7 +46,7 @@ import { getOrganizationRepositories } from '../lib'; * target: https://github.com/backstage/*\/blob/main/catalog-info.yaml * * @public - **/ + */ export class GithubDiscoveryProcessor implements CatalogProcessor { private readonly integrations: ScmIntegrationRegistry; private readonly logger: Logger; diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts index c24cd573e0..2711425998 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.test.ts @@ -181,7 +181,10 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'User', metadata: { - name: 'githubuser', + name: 'user-name', + annotations: { + 'github.com/user-login': 'githubuser', + }, }, spec: { memberOf: [], @@ -192,12 +195,13 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'User', metadata: { - name: 'githubuser', + name: 'user-name', annotations: { 'backstage.io/managed-by-location': 'url:https://github.com/githubuser', 'backstage.io/managed-by-origin-location': 'url:https://github.com/githubuser', + 'github.com/user-login': 'githubuser', }, }, spec: { @@ -211,7 +215,10 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'Group', metadata: { - name: 'mygroup', + name: 'group-name', + annotations: { + 'github.com/team-slug': 'backstage/mygroup', + }, }, spec: { type: 'team', @@ -223,12 +230,13 @@ describe('GithubOrgEntityProvider', () => { apiVersion: 'backstage.io/v1alpha1', kind: 'Group', metadata: { - name: 'mygroup', + name: 'group-name', annotations: { 'backstage.io/managed-by-location': 'url:https://github.com/orgs/backstage/teams/mygroup', 'backstage.io/managed-by-origin-location': 'url:https://github.com/orgs/backstage/teams/mygroup', + 'github.com/team-slug': 'backstage/mygroup', }, }, spec: { diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 3093c2a897..2a888e6f91 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -65,6 +65,11 @@ import { getOrganizationTeam, getOrganizationTeamsFromUsers, } from '../lib/github'; +import { + ANNOTATION_GITHUB_TEAM_SLUG, + ANNOTATION_GITHUB_USER_LOGIN, +} from '../lib/annotation'; +import { splitTeamSlug } from '../lib/util'; /** * Options for {@link GithubOrgEntityProvider}. @@ -602,10 +607,21 @@ export function withLocations( org: string, entity: Entity, ): Entity { + const login = + entity.metadata.annotations?.[ANNOTATION_GITHUB_USER_LOGIN] || + entity.metadata.name; + + let team = entity.metadata.name; + const slug = entity.metadata.annotations?.[ANNOTATION_GITHUB_TEAM_SLUG]; + if (slug) { + const [_, slugTeam] = splitTeamSlug(slug); + team = slugTeam; + } + const location = entity.kind === 'Group' - ? `url:${baseUrl}/orgs/${org}/teams/${entity.metadata.name}` - : `url:${baseUrl}/${entity.metadata.name}`; + ? `url:${baseUrl}/orgs/${org}/teams/${team}` + : `url:${baseUrl}/${login}`; return merge( { metadata: { diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 36696fc777..1f5fc26f38 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.13-next.2 + +### Patch Changes + +- 49948f644f: The config now consistently uses the term 'instance' to refer to a single GitLab API host. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.1.13-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- 52c5685ceb: Implement Group and User Catalog Provider +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/config.d.ts b/plugins/catalog-backend-module-gitlab/config.d.ts index 4f51867efc..00ad0ef032 100644 --- a/plugins/catalog-backend-module-gitlab/config.d.ts +++ b/plugins/catalog-backend-module-gitlab/config.d.ts @@ -31,7 +31,7 @@ export interface Config { host: string; /** * (Optional) Gitlab's group[/subgroup] where the discovery is done. - * If not defined the whole project will be scanned. + * If not defined the whole instance will be scanned. */ group?: string; /** diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index dc9f7c9d3a..6668e2f45d 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.13-next.0", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 1380f51750..1953885783 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.2.0-next.2 + +### Patch Changes + +- 407dc01fc9: Removing extra imports for `run` script as `TestBackend` auto loads the default factories +- 77c41b6924: Updated README to include newer API options for incremental entity providers +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## 0.2.0-next.1 + +### Patch Changes + +- b7e36660d5: Return `EventSubscriber` from `addIncrementalEntityProvider` to hook up to `EventsBackend` +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.2.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/README.md b/plugins/catalog-backend-module-incremental-ingestion/README.md index 0a646e4857..aa23b8dfc1 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/README.md +++ b/plugins/catalog-backend-module-incremental-ingestion/README.md @@ -4,7 +4,7 @@ The Incremental Ingestion catalog backend module provides an Incremental Entity ## Why did we create it? -Backstage provides an [Entity Provider mechanism that has two kinds of mutations](https://backstage.io/docs/features/software-catalog/external-integrations#provider-mutations): `delta` and `full`. `delta` mutations tell Backstage Catalog which entities should be added and removed from the catalog. `full` mutation accepts a list of entities and automatically computes which entities must be removed by comparing the provided entities against existing entities to create a diff between the two sets. These two kinds of mutations are convenient for different kinds of data sources. A `delta` mutation can be used with a data source that emits UPDATE and DELETE events for its data. A `full` mutation is useful for APIs that produce fewer entities than can fit in Backstage processes' memory. +Backstage provides an [Entity Provider mechanism that has two kinds of mutations](https://backstage.io/docs/features/software-catalog/external-integrations#provider-mutations): `delta` and `full`. `delta` mutations tell the Backstage Catalog which entities should be added and removed from the catalog. `full` mutations accept a list of entities and automatically computes which entities must be removed by comparing the provided entities against existing entities to create a diff between the two sets. These two kinds of mutations are convenient for different kinds of data sources. A `delta` mutation can be used with a data source that emits UPDATE and DELETE events for its data. A `full` mutation is useful for APIs that produce fewer entities than can fit in the Backstage processes' memory. Unfortunately, these two kinds of mutations are insufficient for very large data sources for the following reasons, @@ -42,68 +42,80 @@ The Incremental Entity Provider backend is designed for data sources that provid ## Installation 1. Install `@backstage/plugin-catalog-backend-module-incremental-ingestion` with `yarn workspace backend add @backstage/plugin-catalog-backend-module-incremental-ingestion` -2. Import `IncrementalCatalogBuilder` from `@backstage/plugin-catalog-backend-module-incremental-ingestion` and instantiate it with `await IncrementalCatalogBuilder.create(env, builder)`. You have to pass `builder` into `IncrementalCatalogBuilder.create` function because `IncrementalCatalogBuilder` will convert an `IncrementalEntityProvider` into an `EntityProvider` and call `builder.addEntityProvider`. +2. In your catalog.ts, import `IncrementalCatalogBuilder` from `@backstage/plugin-catalog-backend-module-incremental-ingestion` and instantiate it with `await IncrementalCatalogBuilder.create(env, builder)`. You have to pass `builder` into `IncrementalCatalogBuilder.create` function because `IncrementalCatalogBuilder` will convert an `IncrementalEntityProvider` into an `EntityProvider` and call `builder.addEntityProvider`. - ```ts - const builder = CatalogBuilder.create(env); - // incremental builder receives builder because it'll register - // incremental entity providers with the builder - const incrementalBuilder = await IncrementalCatalogBuilder.create( - env, - builder, - ); - ``` +```ts +const builder = CatalogBuilder.create(env); +// incremental builder receives builder because it'll register +// incremental entity providers with the builder +const incrementalBuilder = await IncrementalCatalogBuilder.create(env, builder); +``` -3. Last step, add `await incrementBuilder.build()` after `await builder.build()` to ensure that all `CatalogBuilder` migration run before running `incrementBuilder.build()` migrations. +3. After building the regular `CatalogBuilder`, build the incremental builder: - ```ts - const { processingEngine, router } = await builder.build(); +```ts +// Must be run first to ensure CatalogBuilder database migrations run before Incremental Entity Provider database migrations +const { processingEngine, router } = await builder.build(); - // this has to run after `await builder.build()` to ensure that catalog migrations are completed - // before incremental builder migrations are executed - await incrementalBuilder.build(); - ``` +// Returns an optional - but highly recommended - set of administrative routes +const { incrementalAdminRouter } = await incrementBuilder.build(); +``` - The result should look something like this, +The final result should look something like this, - ```ts - import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; - import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; - import { IncrementalCatalogBuilder } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; - import { Router } from 'express'; - import { Duration } from 'luxon'; - import { PluginEnvironment } from '../types'; +```ts +import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; +import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; +import { IncrementalCatalogBuilder } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; +import { Router } from 'express'; +import { Duration } from 'luxon'; +import { PluginEnvironment } from '../types'; - export default async function createPlugin( - env: PluginEnvironment, - ): Promise { - const builder = CatalogBuilder.create(env); - // incremental builder receives builder because it'll register - // incremental entity providers with the builder - const incrementalBuilder = await IncrementalCatalogBuilder.create( - env, - builder, - ); +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + const builder = CatalogBuilder.create(env); + // incremental builder receives builder because it'll register + // incremental entity providers with the builder + const incrementalBuilder = await IncrementalCatalogBuilder.create( + env, + builder, + ); - builder.addProcessor(new ScaffolderEntitiesProcessor()); + builder.addProcessor(new ScaffolderEntitiesProcessor()); - const { processingEngine, router } = await builder.build(); + const { processingEngine, router } = await builder.build(); + const { incrementalAdminRouter } = await incrementalBuilder.build(); - // this has to run after `await builder.build()` so ensure that catalog migrations are completed - // before incremental builder migrations are executed - const { incrementalAdminRouter } = await incrementalBuilder.build(); + router.use(incrementalAdminRouter); - router.use('/incremental', incrementalAdminRouter); + await processingEngine.start(); - await processingEngine.start(); + return router; +} +``` - return router; - } - ``` +## Administrative Routes + +If you want to manage your incremental entity providers via REST endpoints, the following endpoints are available: + +| Method | Path | Description | +| ------ | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| GET | `/incremental/health` | Checks the health of all incremental providers. Returns array of any unhealthy ones. | +| GET | `/incremental/providers/:provider` | Checks the status of an incremental provider (resting, interstitial, etc). | +| POST | `/incremental/providers/:provider/trigger` | Triggers a provider's next action immediately. E.g., if it's currently interstitial, it will trigger the next burst. | +| POST | `/incremental/providers/:provider/start` | Stop the current ingestion cycle and start a new one immediately. | +| POST | `/incremental/providers/:provider/cancel` | Stop the current ingestion cycle and start a new one in 24 hours. | +| DELETE | `/incremental/providers/:provider` | Completely remove all records for the provider and schedule it to start again in 24 hours. | +| GET | `/incremental/providers/:provider/marks` | Retrieve a list of all ingestion marks for the current ingestion cycle. | +| DELETE | `/incremental/providers/:provider/marks` | Remove all ingestion marks for the current ingestion cycle. | +| POST | `/incremental/cleanup` | Completely remove all records for ALL providers and schedule them to start again in 24 hours. (CAUTION! Can cause orphans!) | + +In all cases, `:provider` is the name of the incremental entity provider. ## Writing an Incremental Entity Provider -To create an Incremental Entity Provider, you need to know how to retrieve a single page of the data that you wish to ingest into the Backstage catalog. If the API has pagination and you know how to make a paginated request to that API, you'll be able to implement an Incremental Entity Provider for this API. For more information about compatibility, checkout Compatible data sources section on this page. +To create an Incremental Entity Provider, you need to know how to retrieve a single page of the data that you wish to ingest into the Backstage catalog. If the API has pagination and you know how to make a paginated request to that API, you'll be able to implement an Incremental Entity Provider for this API. For more information about compatibility, check out the requirements section of this page. Here is the type definition for an Incremental Entity Provider. @@ -114,7 +126,19 @@ interface IncrementalEntityProvider { * operating in the catalog. */ getProviderName(): string; - + /** + * Return a single page of entities from a specific point in the + * ingestion. + * + * @param context - anything needed in order to fetch a single page. + * @param cursor - a unique value identifying the page to ingest. + * @returns The entities to be ingested, as well as the cursor of + * the next page after this one. + */ + next( + context: TContext, + cursor?: TCursor, + ): Promise>; /** * Do any setup and teardown necessary in order to provide the * context for fetching pages. This should always invoke `burst` in @@ -123,24 +147,10 @@ interface IncrementalEntityProvider { * @param burst - a function which performs a series of iterations */ around(burst: (context: TContext) => Promise): Promise; - - /** - * Return a single page of entities from a specific point in the - * ingestion. - * - * @param context - anything needed in order to fetch a single page. - * @param cursor - a unique value identifying the page to ingest. - * @returns the entities to be ingested, as well as the cursor of - * the the next page after this one. - */ - next( - context: TContext, - cursor?: TCursor, - ): Promise>; } ``` -For tutorial, we'll write an Incremental Entity Provider that will call an imaginary API. This imaginary API will return a list of imaginary services. This imaginary API has an imaginary API client with the following interface. +For this tutorial, we'll write an Incremental Entity Provider that will call an imaginary API. This imaginary API will return a list of imaginary services. The imaginary API has an imaginary API client with the following interface. ```ts interface MyApiClient { @@ -157,15 +167,12 @@ interface Service { } ``` -These are the only 3 methods that you need to implement. `getProviderName()` is pretty self explanatory and it's exactly same as on Entity Provider. +These are the only 3 methods that you need to implement. `getProviderName()` is pretty self explanatory and it's identical to the `getProviderName()` method on a regular Entity Provider. ```ts -import { - IncrementalEntityProvider, - EntityIteratorResult, -} from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; +import { IncrementalEntityProvider } from '@backstage/plugin-catalog-backend-module-incremental-ingestion'; -// this will include your pagination information, let's say our API accepts a `page` parameter. +// This will include your pagination information, let's say our API accepts a `page` parameter. // In this case, the cursor will include `page` interface MyApiCursor { page: number; @@ -200,7 +207,7 @@ export class MyIncrementalEntityProvider await burst({ apiClient }); - // if you need to do any teardown, you can do it here + // If you need to do any teardown, you can do it here. } } ``` @@ -306,31 +313,45 @@ We'll assume you followed the Installation instructi ```ts const incrementalBuilder = await IncrementalCatalogBuilder.create(env, builder); -// I'm assuming you're going to get your token from config +// Assuming the token for the API comes from config const token = config.getString('myApiClient.token'); -const myEntityProvider = new MyIncrementalEntityProvider(token) +const myEntityProvider = new MyIncrementalEntityProvider(token); -incrementalBuilder.addIncrementalEntityProvider( - myEntityProvider, - { - // how long should it attempt to read pages from the API - // keep this short. Incremental Entity Provider will attempt to - // read as many pages as it can in this time - burstLength: Duration.fromObject({ seconds: 3 }), - // how long should it wait between bursts? - burstInterval: Duration.fromObject({ seconds: 3 }), - // how long should it rest before re-ingesting again? - restLength: Duration.fromObject({ day: 1 }) - // optional back-off configuration - how long should it wait to retry? - backoff: [ - Duration.fromObject({ seconds: 5 }), - Duration.fromObject({ seconds: 30 }), - Duration.fromObject({ minutes: 10 }), - Duration.fromObject({ hours: 3 }) - ] - } -) +incrementalBuilder.addIncrementalEntityProvider(myEntityProvider, { + // How long should it attempt to read pages from the API in a + // single burst? Keep this short. The Incremental Entity Provider + // will attempt to read as many pages as it can in this time + burstLength: Duration.fromObject({ seconds: 3 }), + + // How long should it wait between bursts? + burstInterval: Duration.fromObject({ seconds: 3 }), + + // How long should it rest before re-ingesting again? + restLength: Duration.fromObject({ day: 1 }), + + // Optional back-off configuration - how long should it wait to retry + // in the event of an error? + backoff: [ + Duration.fromObject({ seconds: 5 }), + Duration.fromObject({ seconds: 30 }), + Duration.fromObject({ minutes: 10 }), + Duration.fromObject({ hours: 3 }), + ], + + // Optional. Use this to prevent removal of entities above a given + // percentage. This can be helpful if a data source is flaky and + // sometimes returns a successful status, but fewer than expected + // assets to add or maintain in the catalog. + rejectRemovalsAbovePercentage: 5, + + // Optional. Similar to rejectRemovalsAbovePercentage, except it + // applies to complete, 100% failure of a data source. If true, + // a data source that returns a successful status but does not + // provide any assets to turn into entities will have its empty + // data set rejected. + rejectEmptySourceCollections: true, +}); ``` That's it!!! diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index c7bb13425a..f6ea81996e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.2.0-next.0", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,7 +36,6 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -56,6 +55,7 @@ }, "devDependencies": { "@backstage/backend-app-api": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^" }, diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index 08d95f4417..e9cc7dbb2a 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -13,20 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { - databaseFactory, - discoveryFactory, - httpRouterFactory, - lifecycleFactory, - loggerFactory, - permissionsFactory, - rootLoggerFactory, - schedulerFactory, - tokenManagerFactory, - urlReaderFactory, -} from '@backstage/backend-app-api'; import { coreServices } from '@backstage/backend-plugin-api'; import { startTestBackend } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; @@ -61,19 +47,7 @@ async function main() { }; await startTestBackend({ - services: [ - [coreServices.config, new ConfigReader(config)], - databaseFactory(), - discoveryFactory(), - httpRouterFactory(), - lifecycleFactory(), - loggerFactory(), - permissionsFactory(), - rootLoggerFactory(), - schedulerFactory(), - tokenManagerFactory(), - urlReaderFactory(), - ], + services: [[coreServices.config, new ConfigReader(config)]], extensionPoints: [], features: [ catalogPlugin(), diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 2ae5a8c2b4..50245d20ae 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## 0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 6553080d2c..6a5e1426f7 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 module that helps integrate towards LDAP", - "version": "0.5.9-next.0", + "version": "0.5.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 6a93a81c5b..0ee67c7a3c 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.0-next.2 + +### Minor Changes + +- fb568e2683: Improve performance when loading users via group membership. + Users data is now loaded from a paged query, rather than having to make an extra call per user to load each user's profiles. + + Note, there are still additional per user calls made to load user avatars + +### Patch Changes + +- 28f9883440: Fixed a bug reading the `user.select` field expected from the `app-config.yaml` configuration +- c5b119ad9c: Increased default page size to 999 (from 100) to reduce the number of calls made to the Microsoft Graph API. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + +## 0.4.8-next.1 + +### Patch Changes + +- 4c86436fdf: Fix MS Graph provider to use target URL for fetching access token +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.4.8-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index a5abdc17c6..09770614b4 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -70,7 +70,11 @@ export const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id'; export class MicrosoftGraphClient { constructor(baseUrl: string, tokenCredential: TokenCredential); static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient; - getGroupMembers(groupId: string): AsyncIterable; + getGroupMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable; // (undocumented) getGroupPhoto(groupId: string, sizeId?: string): Promise; getGroupPhotoWithSizeLimit( @@ -81,6 +85,11 @@ export class MicrosoftGraphClient { query?: ODataQuery, queryMode?: 'basic' | 'advanced', ): AsyncIterable; + getGroupUserMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable; getOrganization(tenantId: string): Promise; // (undocumented) getUserPhoto(userId: string, sizeId?: string): Promise; @@ -88,10 +97,6 @@ export class MicrosoftGraphClient { userId: string, maxSize: number, ): Promise; - getUserProfile( - userId: string, - query?: ODataQuery, - ): Promise; getUsers( query?: ODataQuery, queryMode?: 'basic' | 'advanced', @@ -231,6 +236,7 @@ export type ODataQuery = { expand?: string; select?: string[]; count?: boolean; + top?: number; }; // @public diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 615dfc366f..7ae0af0bea 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 module that helps integrate towards Microsoft Graph", - "version": "0.4.8-next.0", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts index fdaa2a6a43..f7d98f12c6 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.test.ts @@ -70,7 +70,7 @@ describe('MicrosoftGraphClient', () => { expect(await response.json()).toEqual({ value: 'example' }); }); - it('should perform api request with filter, select and expand', async () => { + it('should perform api request with filter, select, expand and top', async () => { worker.use( rest.get('https://example.com/users', (req, res, ctx) => res(ctx.status(200), ctx.json({ queryString: req.url.search })), @@ -81,12 +81,13 @@ describe('MicrosoftGraphClient', () => { filter: 'test eq true', expand: 'children', select: ['id', 'children'], + top: 471, }); expect(response.status).toBe(200); expect(await response.json()).toEqual({ queryString: - '?$filter=test%20eq%20true&$select=id,children&$expand=children', + '?$filter=test%20eq%20true&$select=id,children&$expand=children&$top=471', }); }); @@ -134,33 +135,6 @@ describe('MicrosoftGraphClient', () => { expect(values).toEqual(['first', 'second']); }); - it('should load user profile', async () => { - worker.use( - rest.get('https://example.com/users/user-id', (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - surname: 'Example', - }), - ), - ), - ); - - const userProfile = await client.getUserProfile('user-id'); - - expect(userProfile).toEqual({ surname: 'Example' }); - }); - - it('should throw exception if load user profile fails', async () => { - worker.use( - rest.get('https://example.com/users/user-id', (_, res, ctx) => - res(ctx.status(404)), - ), - ); - - await expect(() => client.getUserProfile('user-id')).rejects.toThrow(); - }); - it('should load user profile photo with max size of 120', async () => { worker.use( rest.get('https://example.com/users/user-id/photos', (_, res, ctx) => @@ -329,6 +303,27 @@ describe('MicrosoftGraphClient', () => { ]); }); + it('should load user group members', async () => { + worker.use( + rest.get( + 'https://example.com/groups/group-id/members/microsoft.graph.user', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + value: [{ id: '12345' }, { id: '67890' }], + }), + ), + ), + ); + + const values = await collectAsyncIterable( + client.getGroupUserMembers('group-id'), + ); + + expect(values).toEqual([{ id: '12345' }, { id: '67890' }]); + }); + it('should load organization', async () => { worker.use( rest.get('https://example.com/organization/tentant-id', (_, res, ctx) => diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts index 321d784543..7a685b258d 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts @@ -52,6 +52,10 @@ export type ODataQuery = { * Retrieves the total count of matching resources. */ count?: boolean; + /** + * Maximum number of records to receive in one batch. + */ + top?: number; }; /** @@ -188,6 +192,7 @@ export class MicrosoftGraphClient { $select: query?.select?.join(','), $expand: query?.expand, $count: query?.count, + $top: query?.top, }, { addQueryPrefix: true, @@ -229,28 +234,6 @@ export class MicrosoftGraphClient { }); } - /** - * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User} - * from Graph API - * - * @public - * @param userId - The unique identifier for the `User` resource - * @param query - OData Query {@link ODataQuery} - * - */ - async getUserProfile( - userId: string, - query?: ODataQuery, - ): Promise { - const response = await this.requestApi(`users/${userId}`, query); - - if (response.status !== 200) { - await this.handleError('user profile', response); - } - - return await response.json(); - } - /** * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto} * of `User` from Graph API with size limit @@ -343,8 +326,37 @@ export class MicrosoftGraphClient { * @param groupId - The unique identifier for the `Group` resource * */ - async *getGroupMembers(groupId: string): AsyncIterable { - yield* this.requestCollection(`groups/${groupId}/members`); + async *getGroupMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable { + yield* this.requestCollection( + `groups/${groupId}/members`, + query, + queryMode, + ); + } + + /** + * Get a collection of + * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User} + * belonging to a `Group` from Graph API and return as `AsyncIterable` + * @public + * @param groupId - The unique identifier for the `Group` resource + * @param query - OData Query {@link ODataQuery} + * @param queryMode - Mode to use while querying. Some features are only available at "advanced". + */ + async *getGroupUserMembers( + groupId: string, + query?: ODataQuery, + queryMode?: 'basic' | 'advanced', + ): AsyncIterable { + yield* this.requestCollection( + `groups/${groupId}/members/microsoft.graph.user/`, + query, + queryMode, + ); } /** diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts index 68c174665d..b02894dfd9 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts @@ -52,6 +52,7 @@ describe('readMicrosoftGraphConfig', () => { authority: 'https://login.example.com/', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', @@ -69,6 +70,7 @@ describe('readMicrosoftGraphConfig', () => { authority: 'https://login.example.com/', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', @@ -167,6 +169,7 @@ describe('readProviderConfigs', () => { user: { expand: 'manager', filter: 'accountEnabled eq true', + select: ['id', 'displayName', 'department'], }, group: { expand: 'member', @@ -196,6 +199,7 @@ describe('readProviderConfigs', () => { queryMode: 'advanced', userExpand: 'manager', userFilter: 'accountEnabled eq true', + userSelect: ['id', 'displayName', 'department'], groupExpand: 'member', groupSelect: ['id', 'displayName', 'description'], groupFilter: 'securityEnabled eq false', diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index 506951ff10..cf4ec646a2 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -264,6 +264,7 @@ export function readProviderConfig( const userExpand = config.getOptionalString('user.expand'); const userFilter = config.getOptionalString('user.filter'); + const userSelect = config.getOptionalStringArray('user.select'); const groupExpand = config.getOptionalString('group.expand'); const groupFilter = config.getOptionalString('group.filter'); @@ -318,6 +319,7 @@ export function readProviderConfig( tenantId, userExpand, userFilter, + userSelect, groupExpand, groupFilter, groupSearch, diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts index bafb2ecaad..b1dfc5a148 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts @@ -61,9 +61,9 @@ function group(data: Partial): GroupEntity { describe('read microsoft graph', () => { const client: jest.Mocked = { getUsers: jest.fn(), - getUserProfile: jest.fn(), getGroups: jest.fn(), getGroupMembers: jest.fn(), + getGroupUserMembers: jest.fn(), getUserPhotoWithSizeLimit: jest.fn(), getGroupPhotoWithSizeLimit: jest.fn(), getOrganization: jest.fn(), @@ -78,13 +78,6 @@ describe('read microsoft graph', () => { mail: 'user.name@example.com', }; } - async function getExampleUserProfile() { - return { - id: 'userid', - displayName: 'User Name', - mail: 'user.name@example.com', - }; - } async function* getExampleGroups() { yield { id: 'groupid', @@ -140,6 +133,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -186,6 +180,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: 'accountEnabled eq true', + top: 999, }, 'advanced', ); @@ -228,6 +223,7 @@ describe('read microsoft graph', () => { { expand: 'manager', filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -242,9 +238,8 @@ describe('read microsoft graph', () => { describe('readMicrosoftGraphUsersInGroups', () => { it('should read users from Groups', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); - client.getUserProfile.mockResolvedValue(getExampleUserProfile()); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -278,16 +273,19 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + select: ['id', 'displayName'], + top: 999, }, undefined, ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: undefined, - }); + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { top: 999 }, + undefined, + ); + expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -297,13 +295,8 @@ describe('read microsoft graph', () => { it('should read users from Groups with advanced query mode', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); - client.getUserProfile.mockResolvedValue({ - id: 'userid', - displayName: 'User Name', - mail: 'user.name@example.com', - }); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -338,16 +331,19 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + select: ['id', 'displayName'], + top: 999, }, 'advanced', ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: undefined, - }); + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { top: 999 }, + 'advanced', + ); + expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -357,8 +353,8 @@ describe('read microsoft graph', () => { it('should read users with userExpand, groupExpand and custom transformer', async () => { client.getGroups.mockImplementation(getExampleGroups); - client.getGroupMembers.mockImplementation(getExampleGroupMembers); - client.getUserProfile.mockResolvedValue(getExampleUserProfile()); + client.getGroupUserMembers.mockImplementation(getExampleUsers); + client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -390,16 +386,22 @@ describe('read microsoft graph', () => { { expand: 'member', filter: 'securityEnabled eq true', + select: ['id', 'displayName'], + top: 999, + }, + undefined, + ); + + expect(client.getGroupUserMembers).toHaveBeenCalledTimes(1); + expect(client.getGroupUserMembers).toHaveBeenCalledWith( + 'groupid', + { + expand: 'manager', + top: 999, }, undefined, ); - expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); - expect(client.getUserProfile).toHaveBeenCalledWith('userid', { - expand: 'manager', - }); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledWith( 'userid', @@ -527,11 +529,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -603,11 +608,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, 'advanced', ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -680,11 +688,14 @@ describe('read microsoft graph', () => { { expand: 'member', filter: 'securityEnabled eq false', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); // TODO: Loading groups photos doesn't work right now as Microsoft Graph // doesn't allows this yet // expect(client.getGroupPhotoWithSizeLimit).toBeCalledTimes(1); @@ -750,11 +761,14 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq true', + top: 999, }, undefined, ); expect(client.getGroupMembers).toHaveBeenCalledTimes(1); - expect(client.getGroupMembers).toHaveBeenCalledWith('groupid'); + expect(client.getGroupMembers).toHaveBeenCalledWith('groupid', { + top: 999, + }); }); }); @@ -887,6 +901,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { filter: undefined, + top: 999, }, undefined, ); @@ -894,6 +909,7 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); @@ -925,6 +941,7 @@ describe('read microsoft graph', () => { { expand: 'manager', filter: 'accountEnabled eq true', + top: 999, }, undefined, ); @@ -932,6 +949,7 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); @@ -960,6 +978,7 @@ describe('read microsoft graph', () => { expect(client.getUsers).toHaveBeenCalledWith( { select: ['mail'], + top: 999, }, undefined, ); @@ -972,13 +991,13 @@ describe('read microsoft graph', () => { }); client.getUsers.mockImplementation(getExampleUsers); - client.getUserProfile.mockImplementation(getExampleUserProfile); client.getUserPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); client.getGroups.mockImplementation(getExampleGroups); client.getGroupMembers.mockImplementation(getExampleGroupMembers); + client.getGroupUserMembers.mockImplementation(getExampleUsers); client.getGroupPhotoWithSizeLimit.mockResolvedValue( 'data:image/jpeg;base64,...', ); @@ -994,16 +1013,18 @@ describe('read microsoft graph', () => { expect(client.getGroups).toHaveBeenCalledWith( { filter: 'name eq backstage-group', + select: ['id', 'displayName'], + top: 999, }, undefined, ); expect(client.getGroups).toHaveBeenCalledWith( { filter: 'securityEnabled eq false', + top: 999, }, undefined, ); - expect(client.getUserProfile).toHaveBeenCalledTimes(1); expect(client.getUserPhotoWithSizeLimit).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 6699af7764..003448a3e8 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -38,6 +38,9 @@ import { defaultOrganizationTransformer, defaultUserTransformer, } from './defaultTransformers'; +import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; + +const PAGE_SIZE = 999; export async function readMicrosoftGraphUsers( client: MicrosoftGraphClient, @@ -52,50 +55,24 @@ export async function readMicrosoftGraphUsers( ): Promise<{ users: UserEntity[]; // With all relations empty }> { - const users: UserEntity[] = []; - const limiter = limiterFactory(10); - - const transformer = options.transformer ?? defaultUserTransformer; - const promises: Promise[] = []; - - for await (const user of client.getUsers( + const users = client.getUsers( { filter: options.userFilter, expand: options.userExpand, select: options.userSelect, + top: PAGE_SIZE, }, options.queryMode, - )) { - // Process all users in parallel, otherwise it can take quite some time - promises.push( - limiter(async () => { - let userPhoto; - try { - userPhoto = await client.getUserPhotoWithSizeLimit( - user.id!, - // We are limiting the photo size, as users with full resolution photos - // can make the Backstage API slow - 120, - ); - } catch (e) { - options.logger.warn(`Unable to load photo for ${user.id}, ${e}`); - } + ); - const entity = await transformer(user, userPhoto); - - if (!entity) { - return; - } - - users.push(entity); - }), - ); - } - - // Wait for all users and photos to be downloaded - await Promise.all(promises); - - return { users }; + return { + users: await transformUsers( + client, + users, + options.logger, + options.transformer, + ), + }; } export async function readMicrosoftGraphUsersInGroups( @@ -113,36 +90,41 @@ export async function readMicrosoftGraphUsersInGroups( ): Promise<{ users: UserEntity[]; // With all relations empty }> { - const users: UserEntity[] = []; - const limiter = limiterFactory(10); - const transformer = options.transformer ?? defaultUserTransformer; const userGroupMemberPromises: Promise[] = []; - const userPromises: Promise[] = []; - - const groupMemberUsers: Set = new Set(); + const userGroupMembers = new Map(); for await (const group of client.getGroups( { expand: options.groupExpand, search: options.userGroupMemberSearch, filter: options.userGroupMemberFilter, + select: ['id', 'displayName'], + top: PAGE_SIZE, }, options.queryMode, )) { // Process all groups in parallel, otherwise it can take quite some time userGroupMemberPromises.push( limiter(async () => { - for await (const member of client.getGroupMembers(group.id!)) { - if (!member.id) { - continue; - } - - if (member['@odata.type'] === '#microsoft.graph.user') { - groupMemberUsers.add(member.id); - } + let groupMemberCount = 0; + for await (const user of client.getGroupUserMembers( + group.id!, + { + expand: options.userExpand, + top: PAGE_SIZE, + }, + options.queryMode, + )) { + userGroupMembers.set(user.id!, user); + groupMemberCount++; } + options.logger.debug('Read users from group', { + groupId: group.id, + groupName: group.displayName, + memberCount: groupMemberCount, + }); }), ); } @@ -150,47 +132,19 @@ export async function readMicrosoftGraphUsersInGroups( // Wait for all group members await Promise.all(userGroupMemberPromises); - options.logger.info(`groupMemberUsers ${groupMemberUsers.size}`); - for (const userId of groupMemberUsers) { - // Process all users in parallel, otherwise it can take quite some time - userPromises.push( - limiter(async () => { - let user; - let userPhoto; - try { - user = await client.getUserProfile(userId, { - expand: options.userExpand, - }); - } catch (e) { - options.logger.warn(`Unable to load user for ${userId}, ${e}`); - } - if (user) { - try { - userPhoto = await client.getUserPhotoWithSizeLimit( - user.id!, - // We are limiting the photo size, as users with full resolution photos - // can make the Backstage API slow - 120, - ); - } catch (e) { - options.logger.warn(`Unable to load userphoto for ${userId}, ${e}`); - } + options.logger.info('Read users from group membership', { + groupCount: userGroupMemberPromises.length, + userCount: userGroupMembers.size, + }); - const entity = await transformer(user, userPhoto); - - if (!entity) { - return; - } - users.push(entity); - } - }), - ); - } - - // Wait for all users and photos to be downloaded - await Promise.all(userPromises); - - return { users }; + return { + users: await transformUsers( + client, + userGroupMembers.values(), + options.logger, + options.transformer, + ), + }; } export async function readMicrosoftGraphOrganization( @@ -248,6 +202,7 @@ export async function readMicrosoftGraphGroups( search: options?.groupSearch, filter: options?.groupFilter, select: options?.groupSelect, + top: PAGE_SIZE, }, options?.queryMode, )) { @@ -269,7 +224,9 @@ export async function readMicrosoftGraphGroups( return; } - for await (const member of client.getGroupMembers(group.id!)) { + for await (const member of client.getGroupMembers(group.id!, { + top: PAGE_SIZE, + })) { if (!member.id) { continue; } @@ -461,6 +418,56 @@ export async function readMicrosoftGraphOrg( return { users, groups }; } +async function transformUsers( + client: MicrosoftGraphClient, + users: Iterable | AsyncIterable, + logger: Logger, + transformer?: UserTransformer, +) { + const limiter = limiterFactory(10); + + const resolvedTransformer = transformer ?? defaultUserTransformer; + const promises: Promise[] = []; + const entities: UserEntity[] = []; + + // Process all users in parallel, otherwise it can take quite some time + for await (const user of users) { + promises.push( + limiter(async () => { + let userPhoto; + try { + userPhoto = await client.getUserPhotoWithSizeLimit( + user.id!, + // We are limiting the photo size, as users with full resolution photos + // can make the Backstage API slow + 120, + ); + } catch (e) { + logger.warn(`Unable to load user photo for`, { + user: user.id, + error: e, + }); + } + + const entity = await resolvedTransformer(user, userPhoto); + + if (entity) { + entities.push(entity); + } + }), + ); + } + + // Wait for all users and photos to be downloaded + await Promise.all(promises); + + logger.debug('Finished transforming users', { + microsoftUserCount: promises.length, + backstageUserCount: entities.length, + }); + return entities; +} + function ensureItem( target: Map>, key: string, diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 0f9b04f997..496221964e 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-node@1.3.3-next.1 + ## 0.1.8-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 798a6d9008..8f08f4b183 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.8-next.0", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 06583f2e9b..329f641c78 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-catalog-backend +## 1.7.2-next.2 + +### Patch Changes + +- e716946103: Updated usage of the lifecycle service. +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + - @backstage/plugin-search-common@1.2.1 + +## 1.7.2-next.1 + +### Patch Changes + +- 2380506364: The process of adding or modifying fields in the software-catalog search index has been simplified. For more details, see [how to customize fields in the Software Catalog index](https://backstage.io/docs/features/search/how-to-guides#how-to-customize-fields-in-the-software-catalog-index). +- 9573651919: The previous migration that adds the `search.original_value` column may leave some of the entities not updated. Add a migration script to trigger a reprocessing of the entities. +- fc73f6aae5: Switched the order of reprocessing statements retroactively in migrations. This only improves the experience for those who at a later time perform a large upgrade of an old Backstage installation. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 1.7.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend/openapi.yaml b/plugins/catalog-backend/openapi.yaml new file mode 100644 index 0000000000..ea09f5da10 --- /dev/null +++ b/plugins/catalog-backend/openapi.yaml @@ -0,0 +1,783 @@ +openapi: 3.1.0 + +info: + title: '@backstage/plugin-catalog-backend' + version: '1' + description: The Backstage backend plugin that provides the Backstage catalog + license: + name: Apache-2.0 + contact: {} + +servers: + - url: / + +components: + examples: {} + headers: {} + parameters: {} + requestBodies: {} + responses: {} + schemas: + RefreshOptions: + type: object + properties: + authorizationToken: + type: string + entityRef: + type: string + description: The reference to a single entity that should be refreshed + required: + - entityRef + description: Options for requesting a refresh of entities in the catalog. + JsonObject: + type: object + properties: {} + description: A type representing all allowed JSON object values. + MapStringString: + type: object + properties: {} + additionalProperties: + type: string + description: Construct a type with a set of properties K of type T + EntityLink: + type: object + properties: + type: + type: string + description: An optional value to categorize links into specific groups + icon: + type: string + description: An optional semantic key that represents a visual icon. + title: + type: string + description: An optional descriptive title for the link. + url: + type: string + description: The url to the external site, document, etc. + required: + - url + description: A link to external information that is related to the entity. + EntityMeta: + allOf: + - $ref: '#/components/schemas/JsonObject' + - type: object + properties: + links: + type: array + items: + $ref: '#/components/schemas/EntityLink' + description: A list of external hyperlinks related to the entity. + tags: + type: array + items: + type: string + description: |- + A list of single-valued strings, to for example classify catalog entities in + various ways. + annotations: + $ref: '#/components/schemas/MapStringString' + labels: + $ref: '#/components/schemas/MapStringString' + description: + type: string + description: |- + A short (typically relatively few words, on one line) description of the + entity. + title: + type: string + description: |- + A display name of the entity, to be presented in user interfaces instead + of the `name` property above, when available. + This field is sometimes useful when the `name` is cumbersome or ends up + being perceived as overly technical. The title generally does not have + as stringent format requirements on it, so it may contain special + characters and be more explanatory. Do keep it very short though, and + avoid situations where a title can be confused with the name of another + entity, or where two entities share a title. + Note that this is only for display purposes, and may be ignored by some + parts of the code. Entity references still always make use of the `name` + property, not the title. + namespace: + type: string + description: The namespace that the entity belongs to. + name: + type: string + description: |- + The name of the entity. + Must be unique within the catalog at any given point in time, for any + given namespace + kind pair. This value is part of the technical + identifier of the entity, and as such it will appear in URLs, database + tables, entity references, and similar. It is subject to restrictions + regarding what characters are allowed. + If you want to use a different, more human readable string with fewer + restrictions on it in user interfaces, see the `title` field below. + etag: + type: string + description: |- + An opaque string that changes for each update operation to any part of + the entity, including metadata. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, and the server will then reject the + operation if it does not match the current stored value. + uid: + type: string + description: |- + A globally unique ID for the entity. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, but the server is free to reject requests + that do so in such a way that it breaks semantics. + required: + - name + description: Metadata fields common to all versions/kinds of entity. + EntityRelation: + type: object + properties: + targetRef: + type: string + description: The entity ref of the target of this relation. + type: + type: string + description: The type of the relation. + required: + - targetRef + - type + description: A relation of a specific type to another entity in the catalog. + Entity: + type: object + properties: + relations: + type: array + items: + $ref: '#/components/schemas/EntityRelation' + description: The relations that this entity has with other entities. + spec: + $ref: '#/components/schemas/JsonObject' + metadata: + $ref: '#/components/schemas/EntityMeta' + kind: + type: string + description: The high level entity type being described. + apiVersion: + type: string + description: |- + The version of specification format for this particular entity that + this is written against. + required: + - metadata + - kind + - apiVersion + description: The parts of the format that's common to all versions/kinds of entity. + EntityAncestryResponse: + type: object + properties: + items: + type: array + items: + type: object + properties: + parentEntityRefs: + items: + type: string + type: array + entity: + $ref: '#/components/schemas/Entity' + required: + - parentEntityRefs + - entity + rootEntityRef: + type: string + required: + - items + - rootEntityRef + EntitiesBatchResponse: + type: object + properties: + items: + type: array + items: + allOf: + - $ref: '#/components/schemas/Entity' + nullable: true + description: |- + The list of entities, in the same order as the refs in the request. Entries + that are null signify that no entity existed with that ref. + required: + - items + EntityFacets: + type: object + properties: + value: + type: string + count: + type: number + description: Construct a type with a set of properties K of type T + EntityFacetsResponse: + type: object + properties: {} + additionalProperties: + $ref: '#/components/schemas/EntityFacets' + required: + - facets + Location: + type: object + properties: + target: + type: string + type: + type: string + id: + type: string + required: + - target + - type + - id + description: Entity location for a specific entity. + LocationSpec: + type: object + properties: + presence: + type: string + enum: + - optional + - required + target: + type: string + type: + type: string + required: + - target + - type + description: Holds the entity location information. + AnalyzeLocationExistingEntity: + type: object + properties: + entity: + $ref: '#/components/schemas/Entity' + isRegistered: + type: boolean + location: + $ref: '#/components/schemas/LocationSpec' + required: + - entity + - isRegistered + - location + description: |- + If the folder pointed to already contained catalog info yaml files, they are + read and emitted like this so that the frontend can inform the user that it + located them and can make sure to register them as well if they weren't + already + RecursivePartial_Entity_: + type: object + properties: + apiVersion: + type: string + description: |- + The version of specification format for this particular entity that + this is written against. + kind: + type: string + description: The high level entity type being described. + metadata: + $ref: '#/components/schemas/EntityMeta' + spec: + $ref: '#/components/schemas/JsonObject' + relations: + type: array + items: + $ref: '#/components/schemas/EntityRelation' + description: The relations that this entity has with other entities. + description: Makes all keys of an entire hierarchy optional. + AnalyzeLocationEntityField: + type: object + properties: + description: + type: string + description: |- + A text to show to the user to inform about the choices made. Like, it could say + "Found a CODEOWNERS file that covers this target, so we suggest leaving this + field empty; which would currently make it owned by X" where X is taken from the + codeowners file. + value: + type: string + nullable: true + state: + type: string + enum: + - analysisSuggestedValue + - analysisSuggestedNoValue + - needsUserInput + description: The outcome of the analysis for this particular field + field: + type: string + description: |- + e.g. "spec.owner"? The frontend needs to know how to "inject" the field into the + entity again if the user wants to change it + required: + - description + - value + - state + - field + AnalyzeLocationGenerateEntity: + type: object + properties: + fields: + type: array + items: + $ref: '#/components/schemas/AnalyzeLocationEntityField' + entity: + $ref: '#/components/schemas/RecursivePartial_Entity_' + required: + - fields + - entity + description: |- + This is some form of representation of what the analyzer could deduce. + We should probably have a chat about how this can best be conveyed to + the frontend. It'll probably contain a (possibly incomplete) entity, plus + enough info for the frontend to know what form data to show to the user + for overriding/completing the info. + AnalyzeLocationResponse: + type: object + properties: + generateEntities: + items: + $ref: '#/components/schemas/AnalyzeLocationGenerateEntity' + type: array + existingEntityFiles: + items: + $ref: '#/components/schemas/AnalyzeLocationExistingEntity' + type: array + required: + - generateEntities + - existingEntityFiles + LocationInput: + type: object + properties: + type: + type: string + target: + type: string + presence: + type: string + enum: + - optional + - required + required: + - type + - target + - presence + SerializedError: + allOf: + - $ref: '#/components/schemas/JsonObject' + - type: object + properties: + code: + type: string + description: A custom code (not necessarily the same as an HTTP response code); may not be present + stack: + type: string + description: A stringified stack trace; may not be present + message: + type: string + description: The message of the exception that was thrown + name: + type: string + description: The name of the exception that was thrown + required: + - message + - name + description: The serialized form of an Error. + securitySchemes: + JWT: + type: http + scheme: bearer + bearerFormat: JWT + +paths: + /refresh: + post: + operationId: RefreshEntity + responses: + '200': + description: Refreshed + security: + # From https://stackoverflow.com/questions/47659324/how-to-specify-an-endpoints-authorization-is-optional-in-openapi-v3 + - {} + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/RefreshOptions' + + /entities: + get: + operationId: GetEntities + responses: + '200': + description: '' + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Entity' + security: + - {} + - JWT: [] + parameters: + - in: query + name: filter + required: false + schema: + type: string + - in: query + name: fields + required: false + schema: + type: string + - in: query + name: offset + required: false + schema: + type: string + - in: query + name: limit + required: false + schema: + type: string + - in: query + name: after + required: false + schema: + type: string + + /entities/by-uid/{uid}: + get: + operationId: GetEntityByUid + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + security: + - {} + - JWT: [] + parameters: + - in: path + name: uid + required: true + schema: + type: string + delete: + operationId: DeleteEntityByUid + responses: + '204': + description: Deleted successfully. + security: + - {} + - JWT: [] + parameters: + - in: path + name: uid + required: true + schema: + type: string + + /entities/by-name/{kind}/{namespace}/{name}: + get: + operationId: GetEntityByName + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Entity' + security: + - {} + - JWT: [] + parameters: + - in: path + name: kind + required: true + schema: + type: string + - in: path + name: namespace + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + + /entities/by-name/{kind}/{namespace}/{name}/ancestry: + get: + operationId: GetEntityAncestryByName + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntityAncestryResponse' + security: + - {} + - JWT: [] + parameters: + - in: path + name: kind + required: true + schema: + type: string + - in: path + name: namespace + required: true + schema: + type: string + - in: path + name: name + required: true + schema: + type: string + + /entities/by-refs: + post: + operationId: GetEntitiesByRefs + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntitiesBatchResponse' + security: + - {} + - JWT: [] + parameters: + - in: query + name: fields + required: false + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: string + + /entity-facets: + get: + operationId: GetEntityFacets + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/EntityFacetsResponse' + security: + - {} + - JWT: [] + parameters: + - in: query + name: facet + required: true + schema: + type: string + - in: query + name: filter + required: false + schema: + type: string + + /locations: + post: + operationId: CreateLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + type: object + properties: + exists: + type: boolean + entities: + items: + $ref: '#/components/schemas/Entity' + type: array + location: + $ref: '#/components/schemas/Location' + required: + - entities + - location + security: + - {} + - JWT: [] + parameters: + - in: query + name: dryRun + required: false + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + presence: + type: string + enum: + - required + - optional + target: + type: string + type: + type: string + required: + - presence + - target + - type + get: + operationId: GetLocations + responses: + '200': + description: Ok + content: + application/json: + schema: + type: array + items: + type: object + properties: + data: + $ref: '#/components/schemas/Location' + required: + - data + security: + - {} + - JWT: [] + parameters: [] + + /locations/{id}: + get: + operationId: GetLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/Location' + security: + - {} + - JWT: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + delete: + operationId: DeleteLocation + responses: + '204': + description: No content + security: + - {} + - JWT: [] + parameters: + - in: path + name: id + required: true + schema: + type: string + + /analyze-location: + post: + operationId: AnalyzeLocation + responses: + '200': + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/AnalyzeLocationResponse' + security: + - {} + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + catalogFileName: + type: string + location: + $ref: '#/components/schemas/LocationInput' + required: + - catalogFileName + - location + + /validate-entity: + post: + operationId: ValidateEntity + responses: + '200': + description: Ok + content: + application/json: + schema: + anyOf: + - type: object + properties: + errors: + $ref: '#/components/schemas/SerializedError' + required: + - errors + - type: object + properties: + errors: + type: array + items: + $ref: '#/components/schemas/SerializedError' + required: + - errors + security: + - {} + - JWT: [] + parameters: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + location: + type: string + entity: + $ref: '#/components/schemas/Entity' + required: + - location + - entity diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 45628825c4..cebd91932b 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": "1.7.2-next.0", + "version": "1.7.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts index 5b34c98ca6..b2630f0f73 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts @@ -25,7 +25,7 @@ describe('createPropertyRule', () => { it('formats the rule description correctly', () => { expect(description).toBe( - 'Allow entities which have the specified metadata subfield.', + 'Allow entities with the specified metadata subfield', ); }); diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts index 19a4423846..fd51a1a060 100644 --- a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts +++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts @@ -22,7 +22,7 @@ import { z } from 'zod'; export const createPropertyRule = (propertyType: 'metadata' | 'spec') => createCatalogPermissionRule({ name: `HAS_${propertyType.toUpperCase()}`, - description: `Allow entities which have the specified ${propertyType} subfield.`, + description: `Allow entities with the specified ${propertyType} subfield`, resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ key: z diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index c24620f41c..ae9b1c3963 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -28,8 +28,7 @@ import { createCatalogPermissionRule } from './util'; */ export const hasAnnotation = createCatalogPermissionRule({ name: 'HAS_ANNOTATION', - description: - 'Allow entities which are annotated with the specified annotation', + description: 'Allow entities with the specified annotation', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ annotation: z.string().describe('Name of the annotation to match on'), diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts index 376534ca6f..16c5917585 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts @@ -25,10 +25,10 @@ import { createCatalogPermissionRule } from './util'; */ export const hasLabel = createCatalogPermissionRule({ name: 'HAS_LABEL', - description: 'Allow entities which have the specified label metadata.', + description: 'Allow entities with the specified label', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ - label: z.string().describe('Name of the label to match one'), + label: z.string().describe('Name of the label to match on'), }), apply: (resource, { label }) => !!resource.metadata.labels?.hasOwnProperty(label), diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index eee7a790b2..94aaa63567 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -25,7 +25,7 @@ import { createCatalogPermissionRule } from './util'; */ export const isEntityKind = createCatalogPermissionRule({ name: 'IS_ENTITY_KIND', - description: 'Allow entities with the specified kind', + description: 'Allow entities matching a specified kind', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ kinds: z diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts index c3bfff5c2e..d0cc1d9280 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts @@ -27,7 +27,7 @@ import { createCatalogPermissionRule } from './util'; */ export const isEntityOwner = createCatalogPermissionRule({ name: 'IS_ENTITY_OWNER', - description: 'Allow entities owned by the current user', + description: 'Allow entities owned by a specified claim', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, paramsSchema: z.object({ claims: z diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index effed7f8f1..5abb630668 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -56,7 +56,7 @@ class CatalogExtensionPointImpl implements CatalogProcessingExtensionPoint { * @alpha */ export const catalogPlugin = createBackendPlugin({ - id: 'catalog', + pluginId: 'catalog', register(env) { const processingExtensions = new CatalogExtensionPointImpl(); // plugins depending on this API will be initialized before this plugins init method is executed. @@ -97,11 +97,7 @@ export const catalogPlugin = createBackendPlugin({ const { processingEngine, router } = await builder.build(); await processingEngine.start(); - lifecycle.addShutdownHook({ - fn: async () => { - await processingEngine.stop(); - }, - }); + lifecycle.addShutdownHook(() => processingEngine.stop()); httpRouter.use(router); }, }); diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index 7ea2f35c98..b5dc4e29e8 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-common +## 1.0.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.0.11-next.0 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index f5c91f3697..2ba16c3d2a 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": "1.0.11-next.0", + "version": "1.0.11-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-customized/CHANGELOG.md b/plugins/catalog-customized/CHANGELOG.md index 6f03f91b9f..f8ff5a85b8 100644 --- a/plugins/catalog-customized/CHANGELOG.md +++ b/plugins/catalog-customized/CHANGELOG.md @@ -1,5 +1,21 @@ # @internal/plugin-catalog-customized +## 0.0.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.0.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + ## 0.0.7-next.0 ### Patch Changes diff --git a/plugins/catalog-customized/package.json b/plugins/catalog-customized/package.json index 27cf26f3f2..9f1e310508 100644 --- a/plugins/catalog-customized/package.json +++ b/plugins/catalog-customized/package.json @@ -1,7 +1,7 @@ { "name": "@internal/plugin-catalog-customized", "description": "The internal Backstage Customizable plugin for browsing the Backstage catalog", - "version": "0.0.7-next.0", + "version": "0.0.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 417fe6ae95..d45fa8f234 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-graph +## 0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.2.27-next.0 ### Patch Changes diff --git a/plugins/catalog-graph/api-report.md b/plugins/catalog-graph/api-report.md index 95f497fe95..f7444c5f1b 100644 --- a/plugins/catalog-graph/api-report.md +++ b/plugins/catalog-graph/api-report.md @@ -65,19 +65,13 @@ export enum Direction { } // @public -export const EntityCatalogGraphCard: (props: { - variant?: InfoCardVariants | undefined; - relationPairs?: RelationPairs | undefined; - maxDepth?: number | undefined; - unidirectional?: boolean | undefined; - mergeRelations?: boolean | undefined; - kinds?: string[] | undefined; - relations?: string[] | undefined; - direction?: Direction | undefined; - height?: number | undefined; - title?: string | undefined; - zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; -}) => JSX.Element; +export const EntityCatalogGraphCard: ( + props: Partial & { + variant?: InfoCardVariants | undefined; + height?: number | undefined; + title?: string | undefined; + }, +) => JSX.Element; // @public export type EntityEdge = DependencyGraphTypes.DependencyEdge; @@ -103,26 +97,27 @@ export type EntityNodeData = { }; // @public -export const EntityRelationsGraph: (props: { +export const EntityRelationsGraph: ( + props: EntityRelationsGraphProps, +) => JSX.Element; + +// @public (undocumented) +export type EntityRelationsGraphProps = { rootEntityNames: CompoundEntityRef | CompoundEntityRef[]; - maxDepth?: number | undefined; - unidirectional?: boolean | undefined; - mergeRelations?: boolean | undefined; - kinds?: string[] | undefined; - relations?: string[] | undefined; - direction?: Direction | undefined; - onNodeClick?: - | ((value: EntityNode, event: MouseEvent_2) => void) - | undefined; - relationPairs?: RelationPairs | undefined; - className?: string | undefined; - zoom?: 'disabled' | 'enabled' | 'enable-on-click' | undefined; - renderNode?: DependencyGraphTypes.RenderNodeFunction | undefined; - renderLabel?: - | DependencyGraphTypes.RenderLabelFunction - | undefined; - curve?: 'curveStepBefore' | 'curveMonotoneX' | undefined; -}) => JSX.Element; + maxDepth?: number; + unidirectional?: boolean; + mergeRelations?: boolean; + kinds?: string[]; + relations?: string[]; + direction?: Direction; + onNodeClick?: (value: EntityNode, event: MouseEvent_2) => void; + relationPairs?: RelationPairs; + className?: string; + zoom?: 'enabled' | 'disabled' | 'enable-on-click'; + renderNode?: DependencyGraphTypes.RenderNodeFunction; + renderLabel?: DependencyGraphTypes.RenderLabelFunction; + curve?: 'curveStepBefore' | 'curveMonotoneX'; +}; // @public export type RelationPairs = [string, string][]; diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 61d517c1dd..aee919241c 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.27-next.0", + "version": "0.2.27-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index b9a15eb569..ae4ad850a4 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -36,8 +36,8 @@ import { Direction, EntityNode, EntityRelationsGraph, - RelationPairs, } from '../EntityRelationsGraph'; +import { EntityRelationsGraphProps } from '../EntityRelationsGraph/EntityRelationsGraph'; const useStyles = makeStyles( { @@ -55,29 +55,26 @@ const useStyles = makeStyles( { name: 'PluginCatalogGraphCatalogGraphCard' }, ); -export const CatalogGraphCard = (props: { - variant?: InfoCardVariants; - relationPairs?: RelationPairs; - maxDepth?: number; - unidirectional?: boolean; - mergeRelations?: boolean; - kinds?: string[]; - relations?: string[]; - direction?: Direction; - height?: number; - title?: string; - zoom?: 'enabled' | 'disabled' | 'enable-on-click'; -}) => { +export const CatalogGraphCard = ( + props: Partial & { + variant?: InfoCardVariants; + height?: number; + title?: string; + }, +) => { const { variant = 'gridItem', relationPairs = ALL_RELATION_PAIRS, maxDepth = 1, unidirectional = true, mergeRelations = true, + direction = Direction.LEFT_RIGHT, kinds, relations, - direction = Direction.LEFT_RIGHT, height, + className, + rootEntityNames, + onNodeClick, title = 'Relations', zoom = 'enable-on-click', } = props; @@ -90,7 +87,7 @@ export const CatalogGraphCard = (props: { const classes = useStyles({ height }); const analytics = useAnalytics(); - const onNodeClick = useCallback( + const defaultOnNodeClick = useCallback( (node: EntityNode, _: MouseEvent) => { const nodeEntityName = parseEntityRef(node.id); const path = catalogEntityRoute({ @@ -113,8 +110,8 @@ export const CatalogGraphCard = (props: { rootEntityRefs: [stringifyEntityRef(entity)], unidirectional, mergeRelations, - kinds, - relations, + selectedKinds: kinds, + selectedRelations: relations, direction, }, { arrayFormat: 'brackets', addQueryPrefix: true }, @@ -133,15 +130,14 @@ export const CatalogGraphCard = (props: { }} > diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index 67aa230ce2..2451f4913a 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -67,11 +67,9 @@ const useStyles = makeStyles( ); /** - * Core building block for custom entity relations diagrams. - * * @public */ -export const EntityRelationsGraph = (props: { +export type EntityRelationsGraphProps = { rootEntityNames: CompoundEntityRef | CompoundEntityRef[]; maxDepth?: number; unidirectional?: boolean; @@ -86,7 +84,14 @@ export const EntityRelationsGraph = (props: { renderNode?: DependencyGraphTypes.RenderNodeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; -}) => { +}; + +/** + * Core building block for custom entity relations diagrams. + * + * @public + */ +export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { const { rootEntityNames, maxDepth = 2, diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts index b86c8f05ae..06227babe3 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/index.ts @@ -14,6 +14,7 @@ * limitations under the License. */ export { EntityRelationsGraph } from './EntityRelationsGraph'; +export type { EntityRelationsGraphProps } from './EntityRelationsGraph'; export { ALL_RELATION_PAIRS } from './relations'; export type { RelationPairs } from './relations'; export { Direction } from './types'; diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 5d4581212a..ee49cb0c3e 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graphql +## 0.3.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.3.18-next.0 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 2f68052900..e66e0e0db2 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.18-next.0", + "version": "0.3.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 51c8ccd448..9c74c13c88 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-catalog-import +## 0.9.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.9.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/plugin-catalog-common@1.0.11-next.0 + ## 0.9.5-next.0 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 7fb456a311..a128aedfd8 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.9.5-next.0", + "version": "0.9.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 7c133e34c2..8d5667e4a6 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-node +## 1.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + +## 1.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + ## 1.3.3-next.0 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index ead9801888..70071dcaea 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.3.3-next.0", + "version": "1.3.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index d1a878b434..662b57550a 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-react +## 1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + +## 1.3.0-next.1 + +### Minor Changes + +- fab93c2fe8: Aligned buttons on "Unregister entity" dialog to keep them on the same line + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + ## 1.3.0-next.0 ### Minor Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 871107e104..c3e6cdda46 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": "1.3.0-next.0", + "version": "1.3.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx index 4173ca85b2..baa4b3732c 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.test.tsx @@ -80,7 +80,11 @@ describe('UnregisterEntityDialog', () => { it('can cancel', async () => { const onClose = jest.fn(); - stateSpy.mockImplementation(() => ({ type: 'loading' })); + stateSpy.mockImplementation(() => ({ + type: 'bootstrap', + location: '', + deleteEntity: jest.fn(), + })); await renderInTestApp( diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx index 48aa2f4012..6c4984129e 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx @@ -39,14 +39,19 @@ const useStyles = makeStyles({ advancedButton: { fontSize: '0.7em', }, + dialogActions: { + display: 'inline-block', + }, }); const Contents = ({ entity, onConfirm, + onClose, }: { entity: Entity; onConfirm: () => any; + onClose: () => any; }) => { const alertApi = useApi(alertApiRef); const configApi = useApi(configApiRef); @@ -92,6 +97,14 @@ const Contents = ({ [alertApi, onConfirm, state], ); + const DialogActionsPanel = () => ( + + + + ); + if (state.type === 'loading') { return ; } @@ -112,15 +125,18 @@ const Contents = ({ {!showDelete && ( - + <> + + + )} {showDelete && ( @@ -140,6 +156,7 @@ const Contents = ({ > Delete Entity + )} @@ -162,6 +179,7 @@ const Contents = ({ > Delete Entity + ); } @@ -258,13 +276,8 @@ export const UnregisterEntityDialog = (props: UnregisterEntityDialogProps) => { Are you sure you want to unregister this entity? - + - - - ); }; diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 4c79fb57a4..204df92577 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-catalog +## 1.8.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 1.8.0-next.1 + +### Minor Changes + +- 0c1fc3986c: Added Markdown support in the `AboutCard` description section +- 0eaa579f89: The `CatalogSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-search-common@1.2.1 + ## 1.7.3-next.0 ### Patch Changes diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 901120bd22..6d746f6a7c 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { StarredEntitiesApi } from '@backstage/plugin-catalog-react'; import { StorageApi } from '@backstage/core-plugin-api'; import { StyleRules } from '@material-ui/core/styles/withStyles'; @@ -108,7 +109,7 @@ export const catalogPlugin: BackstagePlugin< // @public (undocumented) export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 11231894a3..c5e2c675c9 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": "1.7.3-next.0", + "version": "1.8.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/src/apis/StarredEntitiesApi/migration.test.ts b/plugins/catalog/src/apis/StarredEntitiesApi/migration.test.ts index b3bc5400d5..c9083969ee 100644 --- a/plugins/catalog/src/apis/StarredEntitiesApi/migration.test.ts +++ b/plugins/catalog/src/apis/StarredEntitiesApi/migration.test.ts @@ -46,7 +46,7 @@ describe('performMigrationToTheNewBucket', () => { await performMigrationToTheNewBucket({ storageApi: mockStorage }); // read NEW bucket - expect(await newBucket.snapshot('entityRefs').value).toEqual([ + expect(newBucket.snapshot('entityRefs').value).toEqual([ 'component:default/c', 'component:default/a', 'template:custom/b', @@ -72,7 +72,7 @@ describe('performMigrationToTheNewBucket', () => { await performMigrationToTheNewBucket({ storageApi: mockStorage }); // read NEW bucket - expect(await newBucket.snapshot('entityRefs').value).toEqual([ + expect(newBucket.snapshot('entityRefs').value).toEqual([ 'component:default/a', ]); diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index a2b26b87e1..10f06ca09e 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -198,10 +198,12 @@ describe('DefaultCatalogPage', () => { it('should render the default actions of an item in the grid', async () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - expect(await screen.findByText(/Owned \(1\)/)).toBeInTheDocument(); - expect(await screen.findByTitle(/View/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Edit/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Add to favorites/)).toBeInTheDocument(); + await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect(screen.findByTitle(/View/)).resolves.toBeInTheDocument(); + await expect(screen.findByTitle(/Edit/)).resolves.toBeInTheDocument(); + await expect( + screen.findByTitle(/Add to favorites/), + ).resolves.toBeInTheDocument(); }, 20_000); it('should render the custom actions of an item passed as prop', async () => { @@ -226,10 +228,12 @@ describe('DefaultCatalogPage', () => { await renderWrapped(); fireEvent.click(screen.getByTestId('user-picker-owned')); - expect(await screen.findByText(/Owned \(1\)/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Foo Action/)).toBeInTheDocument(); - expect(await screen.findByTitle(/Bar Action/)).toBeInTheDocument(); - expect((await screen.findByTitle(/Bar Action/)).firstChild).toBeDisabled(); + await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); + await expect(screen.findByTitle(/Foo Action/)).resolves.toBeInTheDocument(); + await expect(screen.findByTitle(/Bar Action/)).resolves.toBeInTheDocument(); + await expect( + screen.findByTitle(/Bar Action/).then(e => e.firstChild), + ).resolves.toBeDisabled(); }, 20_000); // this test right now causes some red lines in the log output when running tests @@ -256,7 +260,7 @@ describe('DefaultCatalogPage', () => { await expect(screen.findByText(/Owned \(1\)/)).resolves.toBeInTheDocument(); // The "Starred" menu option should initially be disabled, since there // aren't any starred entities. - await expect(screen.getByTestId('user-picker-starred')).toHaveAttribute( + expect(screen.getByTestId('user-picker-starred')).toHaveAttribute( 'aria-disabled', 'true', ); @@ -269,7 +273,7 @@ describe('DefaultCatalogPage', () => { // Now that we've starred an entity, the "Starred" menu option should be // enabled. - await expect(screen.getByTestId('user-picker-starred')).not.toHaveAttribute( + expect(screen.getByTestId('user-picker-starred')).not.toHaveAttribute( 'aria-disabled', 'true', ); diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index cf60138d99..a277584d2f 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -18,8 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - Divider, - ListItem, ListItemIcon, ListItemText, makeStyles, @@ -31,16 +29,20 @@ import { } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '@backstage/plugin-search-react'; -const useStyles = makeStyles({ - flexContainer: { - flexWrap: 'wrap', +const useStyles = makeStyles( + { + item: {}, + flexContainer: { + flexWrap: 'wrap', + }, + itemText: { + width: '100%', + wordBreak: 'break-all', + marginBottom: '1rem', + }, }, - itemText: { - width: '100%', - wordBreak: 'break-all', - marginBottom: '1rem', - }, -}); + { name: 'CatalogSearchResultListItem' }, +); /** * Props for {@link CatalogSearchResultListItem}. @@ -66,49 +68,44 @@ export function CatalogSearchResultListItem( if (!result) return null; return ( - <> - - {props.icon && {props.icon}} -
    - - {highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - highlight?.fields.text ? ( +
    + {props.icon && {props.icon}} +
    + + {highlight?.fields.title ? ( ) : ( - result.text - ) - } - /> - - {result.kind && ( - - )} - {result.lifecycle && ( - - )} - -
    - - - + result.title + )} + + } + secondary={ + highlight?.fields.text ? ( + + ) : ( + result.text + ) + } + /> + + {result.kind && } + {result.lifecycle && ( + + )} + +
    +
    ); } diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx index 652c9f3873..f8a655413e 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx @@ -78,10 +78,9 @@ describe('CatalogTable component', () => { }, }, ); - const errorMessage = await screen.findByText( - /Could not fetch catalog entities./, - ); - expect(errorMessage).toBeInTheDocument(); + await expect( + screen.findByText(/Could not fetch catalog entities./), + ).resolves.toBeInTheDocument(); }); it('should display entity names when loading has finished and no error occurred', async () => { @@ -306,6 +305,7 @@ describe('CatalogTable component', () => { }, 20_000, ); + it('should render the subtitle when it is specified', async () => { const entity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 935e002375..18080bb7b0 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -16,6 +16,7 @@ import { ANNOTATION_EDIT_URL, ANNOTATION_VIEW_URL, + Entity, RELATION_OWNED_BY, RELATION_PART_OF, } from '@backstage/catalog-model'; @@ -62,6 +63,16 @@ const YellowStar = withStyles({ }, })(Star); +const refCompare = (a: Entity, b: Entity) => { + const toRef = (entity: Entity) => + entity.metadata.title || + humanizeEntityRef(entity, { + defaultKind: 'Component', + }); + + return toRef(a).localeCompare(toRef(b)); +}; + /** @public */ export const CatalogTable = (props: CatalogTableProps) => { const { columns, actions, tableOptions, subtitle, emptyContent } = props; @@ -177,7 +188,7 @@ export const CatalogTable = (props: CatalogTableProps) => { }, ]; - const rows = entities.map(entity => { + const rows = entities.sort(refCompare).map(entity => { const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, { kind: 'system', }); diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index 12c22eb537..ea6ddcaff2 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -31,7 +31,10 @@ import { fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { DefaultStarredEntitiesApi } from './apis'; import { AboutCardProps } from './components/AboutCard'; import { DefaultCatalogPageProps } from './components/CatalogPage'; @@ -254,7 +257,7 @@ export const RelatedEntitiesCard: ( /** @public */ export const CatalogSearchResultListItem: ( - props: CatalogSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = catalogPlugin.provide( createSearchResultListItemExtension({ name: 'CatalogSearchResultListItem', diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 3d1dbae39d..6516506197 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-cicd-statistics@0.1.17-next.2 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-cicd-statistics@0.1.17-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index e3ffb0aa15..2c79050e98 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.11-next.0", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 09a9d200d2..5dcd054002 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-cicd-statistics +## 0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.17-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + ## 0.1.17-next.0 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index d660c758ff..795d8a6c8f 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.17-next.0", + "version": "0.1.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,7 +41,7 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@date-io/luxon": "^1.3.13", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@material-ui/pickers": "^3.3.10", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 0221219b27..701b6f5a86 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-circleci +## 0.3.15-next.2 + +### Patch Changes + +- 1616e06047: Making workflow a link +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.3.15-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.15-next.0 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 7a8c82c7ad..b72b344eeb 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.3.15-next.0", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx index adc8a569bb..22f69ac30f 100644 --- a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -212,6 +212,14 @@ const generatedColumns: TableColumn[] = [ { title: 'Workflow', field: 'workflow.name', + highlight: true, + render: (row: Partial) => ( + + {row?.workflow?.name} + + ), }, { title: 'Actions', diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 23c6373e43..2b2c262778 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-cloudbuild +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.15-next.0 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 3be78201a9..c1ac873f30 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.3.15-next.0", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index b6eae04858..5264e35a96 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-code-climate +## 0.1.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.15-next.0 ### Patch Changes diff --git a/plugins/code-climate/dev/index.tsx b/plugins/code-climate/dev/index.tsx index d5fc4c28e3..060679337e 100644 --- a/plugins/code-climate/dev/index.tsx +++ b/plugins/code-climate/dev/index.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import { createDevApp, EntityGridItem } from '@backstage/dev-utils'; import { Grid } from '@material-ui/core'; import React from 'react'; diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 9bf655af53..9146f3e118 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.15-next.0", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-climate/src/setupTests.ts b/plugins/code-climate/src/setupTests.ts index 43d9e09713..eb4654b869 100644 --- a/plugins/code-climate/src/setupTests.ts +++ b/plugins/code-climate/src/setupTests.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import '@testing-library/jest-dom'; import 'cross-fetch/polyfill'; diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index cff23e1e44..a5e6acae94 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-code-coverage-backend +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index d9966078c9..f9bcefbd5d 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.2.8-next.0", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 70831e5842..5064067470 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-code-coverage +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index b5a0bc93d3..fd15272e38 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.2.8-next.0", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index deb3feb593..d07630cadf 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-codescene +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## 0.1.10-next.0 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.1.9 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 8d2e91b0fd..4249e11064 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.9", + "version": "0.1.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,7 +27,7 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.10", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", "rc-progress": "3.4.1", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 0c9889e2ae..21f079f591 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-config-schema +## 0.1.38-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## 0.1.38-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.1.37 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 436a2c8ca5..95221632e6 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.37", + "version": "0.1.38-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 0828647aac..05d55f3bfe 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-cost-insights +## 0.12.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-cost-insights-common@0.1.1 + +## 0.12.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-cost-insights-common@0.1.1 + ## 0.12.4-next.0 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 449338c32d..02a86793b0 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.12.4-next.0", + "version": "0.12.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx index 0a583aae0d..55d5668189 100644 --- a/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx +++ b/plugins/cost-insights/src/components/CostInsightsLayout/CostInsightsLayout.tsx @@ -37,6 +37,7 @@ type CostInsightsLayoutProps = { }; export const CostInsightsLayout = ({ + title = 'Cost Insights', groups, children, }: PropsWithChildren) => { @@ -46,7 +47,7 @@ export const CostInsightsLayout = ({
    diff --git a/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx b/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx index 9dda1c65e3..69bf8885e7 100644 --- a/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx +++ b/plugins/cost-insights/src/components/EntityCosts/EntityCosts.tsx @@ -120,7 +120,7 @@ export const EntityCostsCard = () => { return {error.message}; } - if (!dailyCost) { + if (!dailyCost || !dailyCost.aggregation.length) { return No daily costs; } diff --git a/plugins/cost-insights/src/example/templates/CostInsightsClient.ts b/plugins/cost-insights/src/example/templates/CostInsightsClient.ts index 50c3bb1470..046196f26b 100644 --- a/plugins/cost-insights/src/example/templates/CostInsightsClient.ts +++ b/plugins/cost-insights/src/example/templates/CostInsightsClient.ts @@ -22,7 +22,7 @@ // IMPORTANT: Remove the lines below to enable type checking and linting // @ts-nocheck -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import { CostInsightsApi, diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index a201886305..e403cf500c 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-dynatrace +## 2.0.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 2.0.0-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 2.0.0-next.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 0a2006f1ad..4cf4a84c33 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "2.0.0-next.0", + "version": "2.0.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,7 +31,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@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" diff --git a/plugins/entity-validation/.eslintrc.js b/plugins/entity-validation/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/entity-validation/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md new file mode 100644 index 0000000000..aa1e41a299 --- /dev/null +++ b/plugins/entity-validation/CHANGELOG.md @@ -0,0 +1,19 @@ +# @backstage/plugin-entity-validation + +## 0.1.0-next.0 + +### Minor Changes + +- d34b3267f9: First implementation for the entity validation UI. For more information refer to its `README.md`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 diff --git a/plugins/entity-validation/README.md b/plugins/entity-validation/README.md new file mode 100644 index 0000000000..1f864d0857 --- /dev/null +++ b/plugins/entity-validation/README.md @@ -0,0 +1,53 @@ +# entity-validation + +This plugin creates a new page in Backstage where the user can validate the entities. + +![Entity Validation](./docs/entity-validation.png) + +## Getting started + +First of all, install the package in the `app` package by running the following command: + +```bash +yarn add --cwd packages/app @backstage/plugin-entity-validation +``` + +Add the new route to the app by adding the following line: + +```typescript +// In packages/app/src/App.tsx +import { EntityValidationPage } from '@backstage/plugin-entity-validation'; + +const routes = ( + + {/* ...other routes */} + } /> + +); +``` + +To add the new page to your sidebar, you must include these lines in your `Root.tsx` file: + +```typescript + // In packages/app/src/components/Root/Root.tsx + import BuildIcon from '@material-ui/icons/Build'; + + ... + + export const Root = ({ children }: PropsWithChildren<{}>) => ( + + + {/* ...other elements */} + }> + {/* Global nav, not org-specific */} + {/* ...other sidebars */} + + {/* End global nav */} + + + {/* ...other elements */} + + {children} + + ); +``` diff --git a/plugins/entity-validation/api-report.md b/plugins/entity-validation/api-report.md new file mode 100644 index 0000000000..2fccbf9471 --- /dev/null +++ b/plugins/entity-validation/api-report.md @@ -0,0 +1,27 @@ +## API Report File for "@backstage/plugin-entity-validation" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteRef } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export const EntityValidationPage: (props: { + defaultYaml?: string | undefined; + defaultLocation?: string | undefined; +}) => JSX.Element; + +// @public (undocumented) +export const entityValidationPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/entity-validation/dev/index.tsx b/plugins/entity-validation/dev/index.tsx new file mode 100644 index 0000000000..1e1dfa760c --- /dev/null +++ b/plugins/entity-validation/dev/index.tsx @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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 { createDevApp } from '@backstage/dev-utils'; +import { entityValidationPlugin, EntityValidationPage } from '../src/plugin'; + +createDevApp() + .registerPlugin(entityValidationPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/entity-validation', + }) + .render(); diff --git a/plugins/entity-validation/docs/entity-validation.png b/plugins/entity-validation/docs/entity-validation.png new file mode 100644 index 0000000000..00cb5fafe0 Binary files /dev/null and b/plugins/entity-validation/docs/entity-validation.png differ diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json new file mode 100644 index 0000000000..6a00e4ad16 --- /dev/null +++ b/plugins/entity-validation/package.json @@ -0,0 +1,68 @@ +{ + "name": "@backstage/plugin-entity-validation", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/entity-validation" + }, + "scripts": { + "start": "backstage-cli package start", + "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" + }, + "dependencies": { + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/theme": "workspace:^", + "@codemirror/language": "^6.0.0", + "@codemirror/legacy-modes": "^6.1.0", + "@codemirror/view": "^6.0.0", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.57", + "@react-hookz/web": "^20.0.0", + "@uiw/react-codemirror": "^4.9.3", + "lodash": "^4.17.21", + "react-use": "^17.2.4", + "yaml": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx b/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx new file mode 100644 index 0000000000..c39f8d5ed7 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityTextArea/EntityTextArea.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 2023 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, { useMemo, useState } from 'react'; +import { Box, makeStyles } from '@material-ui/core'; +import CodeMirror from '@uiw/react-codemirror'; +import { showPanel } from '@codemirror/view'; +import { StreamLanguage } from '@codemirror/language'; +import { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml'; +import { useKeyboardEvent } from '@react-hookz/web'; + +const useStyles = makeStyles(theme => ({ + container: { + position: 'relative', + width: '100%', + height: '100%', + minHeight: '400px', + }, + codeMirror: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + infoPanel: { + color: theme.palette.info.main, + lineHeight: 2, + margin: theme.spacing(0, 1), + }, +})); + +type TemplateTextAreaProps = { + catalogYaml: string; + onChange: (value: string) => void; + onValidate: () => void; +}; + +export const EntityTextArea = ({ + catalogYaml, + onChange, + onValidate, +}: TemplateTextAreaProps) => { + const classes = useStyles(); + const [close, setClose] = useState(false); + + const panelExtension = useMemo(() => { + if (close) { + return showPanel.of(null); + } + + const dom = document.createElement('div'); + dom.classList.add(classes.infoPanel); + dom.textContent = + 'To validate your catalog-info.yaml click on the "Validate" button or use "Ctrl + S" or "Ctrl + Enter"'; + dom.onclick = () => setClose(true); + return showPanel.of(() => ({ dom, top: true })); + }, [classes, close]); + + // Triggers a validation when Ctrl+S or Ctrl+Enter instead of default behavior + useKeyboardEvent( + e => (e.key === 's' || e.key === 'Enter') && (e.ctrlKey || e.metaKey), + e => { + e.preventDefault(); + onValidate(); + }, + ); + + return ( + + { + // Prevent new line if Ctrl + Enter was clicked + if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) e.preventDefault(); + }} + /> + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityTextArea/index.ts b/plugins/entity-validation/src/components/EntityTextArea/index.ts new file mode 100644 index 0000000000..d2a5e41d0f --- /dev/null +++ b/plugins/entity-validation/src/components/EntityTextArea/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './EntityTextArea'; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx b/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx new file mode 100644 index 0000000000..85d47fa2c2 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/EntityResult.tsx @@ -0,0 +1,107 @@ +/* + * Copyright 2023 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, { useState } from 'react'; +import { ValidateEntityResponse } from '@backstage/catalog-client'; +import { useApp } from '@backstage/core-plugin-api'; +import { + Collapse, + IconButton, + ListItem, + ListItemIcon, + ListItemSecondaryAction, + ListItemText, + makeStyles, + Paper, +} from '@material-ui/core'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import WorkIcon from '@material-ui/icons/Work'; +import ExpandLessIcon from '@material-ui/icons/ExpandLess'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { MarkdownContent } from '@backstage/core-components'; +import { ValidationOutputOk } from '../../types'; + +const useStyles = makeStyles(theme => ({ + validationOk: { + color: theme.palette.success.main, + }, + validationNotOk: { + color: theme.palette.error.main, + }, + errorContainer: { + color: theme.palette.error.main, + background: theme.palette.background.paper, + padding: theme.spacing(2), + }, +})); + +type EntityResultProps = { + isFirstError?: boolean; + item: ValidationOutputOk; +}; + +export const EntityResult = ({ + isFirstError = false, + item, +}: EntityResultProps) => { + const classes = useStyles(); + const app = useApp(); + const [expanded, setExpanded] = useState(isFirstError); + + const Icon = + app.getSystemIcon(`kind:${item.entity.kind.toLocaleLowerCase('en-US')}`) ?? + WorkIcon; + + const fetchErrorMessages = (response: ValidateEntityResponse) => { + if (!response.valid) { + return response.errors.map(err => err.message).join('\n\n'); + } + return ''; + }; + + return ( + <> + + + + + setExpanded(!expanded)} + /> + {!item.response.valid && ( + + setExpanded(!expanded)}> + {expanded ? : } + + + )} + + {!item.response.valid && ( + + + + + + )} + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx new file mode 100644 index 0000000000..bc7e22ef54 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/EntityValidationOutput.tsx @@ -0,0 +1,162 @@ +/* + * Copyright 2023 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 { identityApiRef, useApi } from '@backstage/core-plugin-api'; +import { + catalogApiRef, + humanizeEntityRef, +} from '@backstage/plugin-catalog-react'; +import { List, makeStyles, Typography } from '@material-ui/core'; +import useAsync from 'react-use/lib/useAsync'; +import { InfoCard, Progress } from '@backstage/core-components'; +import Alert from '@material-ui/lab/Alert'; +import { + CatalogProcessorResult, + ValidationOutput, + ValidationOutputError, + ValidationOutputOk, +} from '../../types'; +import { EntityResult } from './EntityResult'; + +const useStyles = makeStyles(theme => ({ + validationOk: { + color: theme.palette.success.main, + }, + validationNotOk: { + color: theme.palette.error.main, + }, +})); + +function sortResults(items: Array) { + return items.sort((a, b) => + humanizeEntityRef(a.entity).localeCompare(humanizeEntityRef(b.entity)), + ); +} + +type EntityValidationOutputProps = { + processorResults?: CatalogProcessorResult[]; + locationUrl: string; +}; + +export const EntityValidationOutput = ({ + processorResults, + locationUrl, +}: EntityValidationOutputProps) => { + const classes = useStyles(); + const catalogApi = useApi(catalogApiRef); + const identityApi = useApi(identityApiRef); + + const { value = [], loading } = useAsync(async (): Promise< + ValidationOutput[] | undefined + > => { + if (!processorResults) { + return undefined; + } + + const location = locationUrl + ? `url:${locationUrl}` + : 'url:http://localhost'; + + return await Promise.all( + processorResults.map(async item => { + if (item.type === 'entity') { + const { token } = await identityApi.getCredentials(); + + const validateResult = await catalogApi.validateEntity( + item.entity, + location, + { + token, + }, + ); + return { + type: 'valid', + entity: item.entity, + response: validateResult, + }; + } else if (item.type === 'error') { + return { + type: 'error', + processingError: `Malformed entity YAML, ${item.error}`, + }; + } + return { + type: 'error', + processingError: `Internal error, failed to parse entity`, + }; + }), + ); + }, [processorResults]); + + if (loading) { + return ; + } + + const errors = value.filter( + v => v.type === 'error', + ) as ValidationOutputError[]; + + const results = sortResults( + value.filter(v => v.type === 'valid') as ValidationOutputOk[], + ); + // If there are any errors, only the first one will be expanded + const firstErrorIndex = results.findIndex(r => !r.response.valid); + + if (errors.length !== 0) { + return ( + <> + {errors.map(err => ( + {err.processingError} + ))} + + ); + } + + return ( + + {results.length === 0 ? ( +
    + + No entity definitions found or validated yet + +
    + ) : ( + <> + + {results.map((item, key) => ( + + ))} + +
    + {results.every(r => r.response.valid) ? ( + + All the entities are valid! + + ) : ( + + One or more entities have validation errors + + )} +
    + + )} +
    + ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationOutput/index.ts b/plugins/entity-validation/src/components/EntityValidationOutput/index.ts new file mode 100644 index 0000000000..8d327581c6 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationOutput/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './EntityValidationOutput'; +export * from './EntityResult'; diff --git a/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx new file mode 100644 index 0000000000..dc86af8763 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationPage/EntityValidationPage.tsx @@ -0,0 +1,120 @@ +/* + * Copyright 2023 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, { useState } from 'react'; +import { Button, Content, Header, Page } from '@backstage/core-components'; +import { EntityTextArea } from '../EntityTextArea'; +import { Grid, TextField } from '@material-ui/core'; +import { CatalogProcessorResult } from '../../types'; +import { parseEntityYaml } from '../../utils'; +import { EntityValidationOutput } from '../EntityValidationOutput'; + +const EXAMPLE_CATALOG_INFO_YAML = `# Put your catalog-info.yaml below and validate it +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: test + description: Component description + links: [] + tags: [] + annotations: {} +spec: + type: service + lifecycle: experimental + owner: owner +`; + +export const EntityValidationPage = (props: { + defaultYaml?: string; + defaultLocation?: string; +}) => { + const { + defaultYaml = EXAMPLE_CATALOG_INFO_YAML, + defaultLocation = 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + } = props; + + const [catalogYaml, setCatalogYaml] = useState(defaultYaml); + const [yamlFiles, setYamlFiles] = useState(); + const [locationUrl, setLocationUrl] = useState(''); + + const parseYaml = () => { + const parsedFiles = [ + ...parseEntityYaml(Buffer.from(catalogYaml), { + type: 'url', + target: locationUrl ? locationUrl : 'http://localhost', + }), + ]; + setYamlFiles(parsedFiles); + }; + + return ( + +
    + + + + setLocationUrl(e.target.value)} + /> + + + + + + + + + + + + setCatalogYaml(value)} + catalogYaml={catalogYaml} + /> + + + + + + + + + + + + ); +}; diff --git a/plugins/entity-validation/src/components/EntityValidationPage/index.ts b/plugins/entity-validation/src/components/EntityValidationPage/index.ts new file mode 100644 index 0000000000..24149a9387 --- /dev/null +++ b/plugins/entity-validation/src/components/EntityValidationPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './EntityValidationPage'; diff --git a/plugins/entity-validation/src/index.ts b/plugins/entity-validation/src/index.ts new file mode 100644 index 0000000000..33ae575dfe --- /dev/null +++ b/plugins/entity-validation/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { entityValidationPlugin, EntityValidationPage } from './plugin'; diff --git a/plugins/entity-validation/src/plugin.test.ts b/plugins/entity-validation/src/plugin.test.ts new file mode 100644 index 0000000000..eae69e8d3a --- /dev/null +++ b/plugins/entity-validation/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { entityValidationPlugin } from './plugin'; + +describe('entity-validation', () => { + it('should export plugin', () => { + expect(entityValidationPlugin).toBeDefined(); + }); +}); diff --git a/plugins/entity-validation/src/plugin.ts b/plugins/entity-validation/src/plugin.ts new file mode 100644 index 0000000000..9a3014da28 --- /dev/null +++ b/plugins/entity-validation/src/plugin.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 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 { + createComponentExtension, + createPlugin, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const entityValidationPlugin = createPlugin({ + id: 'entity-validation', + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const EntityValidationPage = entityValidationPlugin.provide( + createComponentExtension({ + name: 'EntityValidationPage', + component: { + lazy: () => + import('./components/EntityValidationPage').then( + m => m.EntityValidationPage, + ), + }, + }), +); diff --git a/plugins/entity-validation/src/processingResult.ts b/plugins/entity-validation/src/processingResult.ts new file mode 100644 index 0000000000..de9d8adbbd --- /dev/null +++ b/plugins/entity-validation/src/processingResult.ts @@ -0,0 +1,73 @@ +/* + * 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. + */ + +// File copied from https://github.com/backstage/backstage/blob/master/plugins/catalog-node/src/api/processingResult.ts +import { InputError, NotFoundError } from '@backstage/errors'; +import { Entity } from '@backstage/catalog-model'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { CatalogProcessorResult, EntityRelationSpec } from './types'; + +/** + * Factory functions for the standard processing result types. + * + * @public + */ +export const processingResult = Object.freeze({ + notFoundError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { + type: 'error', + location: atLocation, + error: new NotFoundError(message), + }; + }, + + inputError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { + type: 'error', + location: atLocation, + error: new InputError(message), + }; + }, + + generalError( + atLocation: LocationSpec, + message: string, + ): CatalogProcessorResult { + return { type: 'error', location: atLocation, error: new Error(message) }; + }, + + location(newLocation: LocationSpec): CatalogProcessorResult { + return { type: 'location', location: newLocation }; + }, + + entity(atLocation: LocationSpec, newEntity: Entity): CatalogProcessorResult { + return { type: 'entity', location: atLocation, entity: newEntity }; + }, + + relation(spec: EntityRelationSpec): CatalogProcessorResult { + return { type: 'relation', relation: spec }; + }, + + refresh(key: string): CatalogProcessorResult { + return { type: 'refresh', key }; + }, +} as const); diff --git a/plugins/entity-validation/src/routes.ts b/plugins/entity-validation/src/routes.ts new file mode 100644 index 0000000000..8cdc138782 --- /dev/null +++ b/plugins/entity-validation/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'entity-validation', +}); diff --git a/plugins/entity-validation/src/setupTests.ts b/plugins/entity-validation/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/entity-validation/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/entity-validation/src/types.ts b/plugins/entity-validation/src/types.ts new file mode 100644 index 0000000000..7ecc27bb25 --- /dev/null +++ b/plugins/entity-validation/src/types.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2023 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 { CompoundEntityRef, Entity } from '@backstage/catalog-model'; +import { ValidateEntityResponse } from '@backstage/catalog-client'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; + +export type ValidationOutputError = { + type: 'error'; + processingError: string; +}; + +export type ValidationOutputOk = { + type: 'valid'; + entity: Entity; + response: ValidateEntityResponse; +}; + +export type ValidationOutput = ValidationOutputOk | ValidationOutputError; + +export type EntityRelationSpec = { + /** + * The source entity of this relation. + */ + source: CompoundEntityRef; + + /** + * The type of the relation. + */ + type: string; + + /** + * The target entity of this relation. + */ + target: CompoundEntityRef; +}; + +type CatalogProcessorLocationResult = { + type: 'location'; + location: LocationSpec; +}; + +type CatalogProcessorEntityResult = { + type: 'entity'; + entity: Entity; + location: LocationSpec; +}; + +type CatalogProcessorRelationResult = { + type: 'relation'; + relation: EntityRelationSpec; +}; + +type CatalogProcessorErrorResult = { + type: 'error'; + error: Error; + location: LocationSpec; +}; + +type CatalogProcessorRefreshKeysResult = { + type: 'refresh'; + key: string; +}; + +export type CatalogProcessorResult = + | CatalogProcessorLocationResult + | CatalogProcessorEntityResult + | CatalogProcessorRelationResult + | CatalogProcessorErrorResult + | CatalogProcessorRefreshKeysResult; diff --git a/plugins/entity-validation/src/utils.ts b/plugins/entity-validation/src/utils.ts new file mode 100644 index 0000000000..d81de6f6c9 --- /dev/null +++ b/plugins/entity-validation/src/utils.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2023 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, stringifyLocationRef } from '@backstage/catalog-model'; +import lodash from 'lodash'; +import yaml from 'yaml'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { CatalogProcessorResult } from './types'; +import { processingResult } from './processingResult'; + +// Copy from: https://github.com/backstage/backstage/blob/master/plugins/catalog-backend/src/modules/util/parse.ts +export function* parseEntityYaml( + data: Buffer, + location: LocationSpec, +): Iterable { + let documents: yaml.Document.Parsed[]; + try { + documents = yaml.parseAllDocuments(data.toString('utf8')).filter(d => d); + } catch (e) { + const loc = stringifyLocationRef(location); + const message = `Failed to parse YAML at ${loc}, ${e}`; + yield processingResult.generalError(location, message); + return; + } + + for (const document of documents) { + if (document.errors?.length) { + const loc = stringifyLocationRef(location); + const message = `YAML error at ${loc}, ${document.errors[0]}`; + yield processingResult.generalError(location, message); + } else { + const json = document.toJSON(); + if (lodash.isPlainObject(json)) { + yield processingResult.entity(location, json as Entity); + } else if (json === null) { + // Ignore null values, these happen if there is an empty document in the + // YAML file, for example if --- is added to the end of the file. + } else { + const message = `Expected object at root, got ${typeof json}`; + yield processingResult.generalError(location, message); + } + } + } +} diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 4086a1f7a2..31596ba402 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index e76e71ecfe..bf06d46648 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 6b76965e00..83fadeba7b 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 68d3b0a2ad..12420646ae 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 2141562a13..6808429921 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 7a2b599885..04e6248a5f 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index 11b37dd443..e05890268c 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 199077d990..59cded8497 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 3ece4590aa..88fe36262b 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-github +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index 9975107d17..6d1fb5b412 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index 87e478b56a..4265fa2c71 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index a09577ae0e..ad0b497421 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index c786d4540e..713df91935 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index fa99c54da1..9df1f423e1 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index ea8e4a2c47..1d3ae288b4 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-events-backend +## 0.2.3-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-events-node@0.2.3-next.2 + - @backstage/config@1.0.6 + +## 0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-events-node@0.2.3-next.1 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 375fdd9034..1154fc0633 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.3-next.0", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/src/service/EventsPlugin.ts b/plugins/events-backend/src/service/EventsPlugin.ts index 29456d71f7..402104b56c 100644 --- a/plugins/events-backend/src/service/EventsPlugin.ts +++ b/plugins/events-backend/src/service/EventsPlugin.ts @@ -80,7 +80,7 @@ class EventsExtensionPointImpl implements EventsExtensionPoint { * @alpha */ export const eventsPlugin = createBackendPlugin({ - id: 'events', + pluginId: 'events', register(env) { const extensionPoint = new EventsExtensionPointImpl(); env.registerExtensionPoint(eventsExtensionPoint, extensionPoint); diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index 61e19f995b..99423d1f4a 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-events-node +## 0.2.3-next.2 + +### Patch Changes + +- 19d4abf72c: Make `EventParams` typed for implementing tidier event handling. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + +## 0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + ## 0.2.3-next.0 ### Patch Changes diff --git a/plugins/events-node/api-report.md b/plugins/events-node/api-report.md index 51136fd301..8428003b85 100644 --- a/plugins/events-node/api-report.md +++ b/plugins/events-node/api-report.md @@ -14,8 +14,8 @@ export interface EventBroker { } // @public (undocumented) -export interface EventParams { - eventPayload: unknown; +export interface EventParams { + eventPayload: TPayload; metadata?: Record; topic: string; } diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 9be7706e1e..e1b784c6c4 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.3-next.0", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/src/api/EventParams.ts b/plugins/events-node/src/api/EventParams.ts index 6912827281..19a562aee0 100644 --- a/plugins/events-node/src/api/EventParams.ts +++ b/plugins/events-node/src/api/EventParams.ts @@ -17,7 +17,7 @@ /** * @public */ -export interface EventParams { +export interface EventParams { /** * Topic for which this event should be published. */ @@ -25,7 +25,7 @@ export interface EventParams { /** * Event payload. */ - eventPayload: unknown; + eventPayload: TPayload; /** * Metadata (e.g., HTTP headers and similar for events received from external). */ diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index b3db395424..d2212665fd 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @internal/plugin-todo-list-backend +## 1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 1.0.10-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-backend/api-report.md b/plugins/example-todo-list-backend/api-report.md index c4f8665a70..319fbbf226 100644 --- a/plugins/example-todo-list-backend/api-report.md +++ b/plugins/example-todo-list-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 { BackendFeature } from '@backstage/backend-plugin-api'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public export function createRouter(options: RouterOptions): Promise; +// @alpha +export const exampleTodoListPlugin: () => BackendFeature; + // @public export interface RouterOptions { // (undocumented) diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 123f2c78ad..5cda8b5f52 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.10-next.0", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,11 +11,12 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -24,6 +25,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -42,6 +44,7 @@ "supertest": "^6.1.6" }, "files": [ - "dist" + "dist", + "alpha" ] } diff --git a/plugins/example-todo-list-backend/src/index.ts b/plugins/example-todo-list-backend/src/index.ts index ca73cb27ba..6917307db6 100644 --- a/plugins/example-todo-list-backend/src/index.ts +++ b/plugins/example-todo-list-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { exampleTodoListPlugin } from './plugin'; diff --git a/plugins/example-todo-list-backend/src/plugin.ts b/plugins/example-todo-list-backend/src/plugin.ts new file mode 100644 index 0000000000..42985f6e88 --- /dev/null +++ b/plugins/example-todo-list-backend/src/plugin.ts @@ -0,0 +1,48 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The example TODO list backend plugin. + * + * @alpha + */ +export const exampleTodoListPlugin = createBackendPlugin({ + pluginId: 'exampleTodoList', + register(env) { + env.registerInit({ + deps: { + identity: coreServices.identity, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ identity, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + identity, + logger: loggerToWinstonLogger(logger), + }), + ); + }, + }); + }, +}); diff --git a/plugins/example-todo-list/.eslintrc.js b/plugins/example-todo-list/.eslintrc.js index 8c18e76229..e2a53a6ad2 100644 --- a/plugins/example-todo-list/.eslintrc.js +++ b/plugins/example-todo-list/.eslintrc.js @@ -1,14 +1 @@ -module.exports = { - extends: [require.resolve('@backstage/cli/config/eslint')], - rules: { - 'import/no-extraneous-dependencies': [ - 'error', - { - devDependencies: true, - optionalDependencies: true, - peerDependencies: true, - bundledDependencies: true, - }, - ], - }, -}; +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 66c920d08b..6b0da992bc 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,23 @@ # @internal/plugin-todo-list +## 1.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 1.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 1.0.9 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index ce8197bc6e..7d4378b51f 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.9", + "version": "1.0.10-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index b2465ea308..80503f396a 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-explore-backend +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + +## 0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.0.4-next.0 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 399f4df018..77b6b05374 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.4-next.0", + "version": "0.0.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index e6d5dd2ecc..58f14ca14d 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-explore +## 0.4.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + +## 0.4.0-next.1 + +### Minor Changes + +- 0eaa579f89: The `ToolSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-explore-common@0.0.1 + - @backstage/plugin-explore-react@0.0.25 + - @backstage/plugin-search-common@1.2.1 + ## 0.3.46-next.0 ### Patch Changes diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index e7adde4b77..da960ae951 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -19,6 +19,7 @@ import { IndexableDocument } from '@backstage/plugin-search-common'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TabProps } from '@material-ui/core'; // @public @deprecated (undocumented) @@ -126,7 +127,7 @@ export const ToolExplorerContent: (props: { // @public (undocumented) export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 6700ba09e8..888040e1cb 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.46-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index c9e8946f26..eb12ba45d8 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -18,8 +18,6 @@ import React, { ReactNode } from 'react'; import { Box, Chip, - Divider, - ListItem, ListItemIcon, ListItemText, makeStyles, @@ -64,46 +62,42 @@ export function ToolSearchResultListItem(props: ToolSearchResultListItemProps) { return ( <> - - {props.icon && {props.icon}} -
    - - {props.highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - props.highlight?.fields.text ? ( + {props.icon && {props.icon}} +
    + + {props.highlight?.fields.title ? ( ) : ( - result.text - ) - } - /> - - {result.tags && - result.tags.map((tag: string) => ( - - ))} - -
    - - + result.title + )} + + } + secondary={ + props.highlight?.fields.text ? ( + + ) : ( + result.text + ) + } + /> + + {result.tags?.map((tag: string) => ( + + ))} + +
    ); } diff --git a/plugins/explore/src/plugin.ts b/plugins/explore/src/plugin.ts index 5a4bec53c5..84e7657355 100644 --- a/plugins/explore/src/plugin.ts +++ b/plugins/explore/src/plugin.ts @@ -22,7 +22,10 @@ import { discoveryApiRef, fetchApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { ExploreClient, exploreApiRef } from './api'; import { ToolSearchResultListItemProps } from './components/ToolSearchResultListItem'; // import { exampleTools } from './util/examples'; @@ -70,7 +73,7 @@ export const explorePlugin = createPlugin({ /** @public */ export const ToolSearchResultListItem: ( - props: ToolSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = explorePlugin.provide( createSearchResultListItemExtension({ name: 'ToolSearchResultListItem', diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 60d4bad35f..c4660e5479 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-firehydrant +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.32-next.0 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index bd1536d76f..8edcade92b 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.32-next.0", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index d91bd1e0b2..1e906085e4 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-fossa +## 0.2.47-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.47-next.0 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 131ea2f747..a93d3b3922 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.47-next.0", + "version": "0.2.47-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 8155123f67..5134ae8c3f 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-gcalendar +## 0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## 0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.3.10 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index dd6c804f98..5c84ebe6cb 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.10", + "version": "0.3.11-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 67ac992174..405a344b28 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-gcp-projects +## 0.3.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.3.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.33 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 193ab0af28..54bfc85dd2 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.33", + "version": "0.3.34-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 6d59cae145..3fee0c167b 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-git-release-manager +## 0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + +## 0.3.28-next.0 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 0.3.27 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index d3273e686d..171a909b74 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.27", + "version": "0.3.28-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 4f291714f6..5ae3bafb5d 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-github-actions +## 0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.5.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 0.5.15-next.0 ### Patch Changes diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index ee761b3504..93e6ee4f74 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -22,6 +22,8 @@ import { Entity } from '@backstage/catalog-model'; import { GithubActionsApi, githubActionsApiRef } from '../src'; import getWorkflowRunResponse from '../src/__fixtures__/get-workflow-run.json'; import listJobsForWorkflowRunResponse from '../src/__fixtures__/list-jobs-for-workflow-run.json'; +import listWorkflowRuns from '../src/__fixtures__/list-workflow-runs.json'; +import { downloadJobLogsForWorkflowRun } from '../src/__fixtures__/downloadJobLogsForWorkflowRun'; const mockEntity: Entity = { apiVersion: 'backstage.io/v1alpha1', @@ -41,7 +43,9 @@ const mockEntity: Entity = { }; const mockGithubActionsApi: GithubActionsApi = { - async downloadJobLogsForWorkflowRun() {}, + async downloadJobLogsForWorkflowRun() { + return downloadJobLogsForWorkflowRun; + }, async getWorkflow() { return {} as any; }, @@ -52,7 +56,7 @@ const mockGithubActionsApi: GithubActionsApi = { return listJobsForWorkflowRunResponse as any; }, async listWorkflowRuns() { - return {} as any; + return listWorkflowRuns as any; }, async reRunWorkflow() { return {} as any; diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 2fd5234847..5165820d62 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.5.15-next.0", + "version": "0.5.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts b/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts new file mode 100644 index 0000000000..7b882d0719 --- /dev/null +++ b/plugins/github-actions/src/__fixtures__/downloadJobLogsForWorkflowRun.ts @@ -0,0 +1,315 @@ +/* + * 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 const downloadJobLogsForWorkflowRun = ` +2022-12-09T17:25:25.6542422Z Requested labels: ubuntu-latest +2022-12-09T17:25:25.6542470Z Job defined at: octo-org/octo-template/dynamic/pages/pages-build-deployment@refs/heads/main +2022-12-09T17:25:25.6542493Z Waiting for a runner to pick up this job... +2022-12-09T17:25:25.9157301Z Job is waiting for a hosted runner to come online. +2022-12-09T17:25:29.3998345Z Job is about to start running on the hosted runner: Hosted Agent (hosted) +2022-12-09T17:25:31.7099053Z Current runner version: '2.299.1' +2022-12-09T17:25:31.7123983Z ##[group]Operating System +2022-12-09T17:25:31.7124496Z Ubuntu +2022-12-09T17:25:31.7124859Z 22.04.1 +2022-12-09T17:25:31.7125085Z LTS +2022-12-09T17:25:31.7125353Z ##[endgroup] +2022-12-09T17:25:31.7125657Z ##[group]Runner Image +2022-12-09T17:25:31.7125963Z Image: ubuntu-22.04 +2022-12-09T17:25:31.7126295Z Version: 20221204.2 +2022-12-09T17:25:31.7127048Z Included Software: https://github.com/actions/runner-images/blob/ubuntu22/20221204.2/images/linux/Ubuntu2204-Readme.md +2022-12-09T17:25:31.7127614Z Image Release: https://github.com/actions/runner-images/releases/tag/ubuntu22%2F20221204.2 +2022-12-09T17:25:31.7128026Z ##[endgroup] +2022-12-09T17:25:31.7128400Z ##[group]Runner Image Provisioner +2022-12-09T17:25:31.7128722Z 2.0.91.1 +2022-12-09T17:25:31.7128945Z ##[endgroup] +2022-12-09T17:25:31.7129586Z ##[group]GITHUB_TOKEN Permissions +2022-12-09T17:25:31.7130130Z Contents: read +2022-12-09T17:25:31.7130387Z Metadata: read +2022-12-09T17:25:31.7130849Z Pages: write +2022-12-09T17:25:31.7131169Z ##[endgroup] +2022-12-09T17:25:31.7134756Z Secret source: Actions +2022-12-09T17:25:31.7135232Z Prepare workflow directory +2022-12-09T17:25:31.7951647Z Prepare all required actions +2022-12-09T17:25:31.8134091Z Getting action download info +2022-12-09T17:25:32.1190857Z Download action repository 'actions/checkout@v3' (SHA:93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8) +2022-12-09T17:25:32.4403240Z Download action repository 'actions/jekyll-build-pages@v1' (SHA:9b882383c88a22eef81e9c1a5a232c2ff9a6672b) +2022-12-09T17:25:32.7457755Z Download action repository 'actions/upload-pages-artifact@v1' (SHA:c8641e80048cf33d329c39df3bcc53196178335a) +2022-12-09T17:25:33.0262452Z Getting action download info +2022-12-09T17:25:33.1786870Z Download action repository 'actions/upload-artifact@main' (SHA:83fd05a356d7e2593de66fc9913b3002723633cb) +2022-12-09T17:25:33.4537715Z ##[group]Pull down action image 'ghcr.io/actions/jekyll-build-pages:v1.0.4' +2022-12-09T17:25:33.4611360Z ##[command]/usr/bin/docker pull ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:34.0231935Z v1.0.4: Pulling from actions/jekyll-build-pages +2022-12-09T17:25:34.0232298Z eff15d958d66: Pulling fs layer +2022-12-09T17:25:34.0232609Z 923e91ae3a1b: Pulling fs layer +2022-12-09T17:25:34.0232986Z 2aa5d3a4a151: Pulling fs layer +2022-12-09T17:25:34.0233248Z bc64adf2d0b2: Pulling fs layer +2022-12-09T17:25:34.0233543Z bfc5cca7d80e: Pulling fs layer +2022-12-09T17:25:34.0233827Z 61b6e3e25463: Pulling fs layer +2022-12-09T17:25:34.0234080Z 7c62fb63f605: Pulling fs layer +2022-12-09T17:25:34.0234380Z 0f68cc81f8f6: Pulling fs layer +2022-12-09T17:25:34.0234663Z 09f325326117: Pulling fs layer +2022-12-09T17:25:34.0234894Z a73a0a50c4db: Pulling fs layer +2022-12-09T17:25:34.0235171Z bc64adf2d0b2: Waiting +2022-12-09T17:25:34.0235470Z bfc5cca7d80e: Waiting +2022-12-09T17:25:34.0235840Z 61b6e3e25463: Waiting +2022-12-09T17:25:34.0236104Z 7c62fb63f605: Waiting +2022-12-09T17:25:34.0236314Z 0f68cc81f8f6: Waiting +2022-12-09T17:25:34.0236586Z 09f325326117: Waiting +2022-12-09T17:25:34.0236855Z a73a0a50c4db: Waiting +2022-12-09T17:25:34.1800756Z 2aa5d3a4a151: Verifying Checksum +2022-12-09T17:25:34.1801065Z 2aa5d3a4a151: Download complete +2022-12-09T17:25:34.4333121Z eff15d958d66: Verifying Checksum +2022-12-09T17:25:34.4335284Z eff15d958d66: Download complete +2022-12-09T17:25:34.5215161Z bc64adf2d0b2: Verifying Checksum +2022-12-09T17:25:34.5231169Z bc64adf2d0b2: Download complete +2022-12-09T17:25:34.5266358Z 923e91ae3a1b: Verifying Checksum +2022-12-09T17:25:34.5266637Z 923e91ae3a1b: Download complete +2022-12-09T17:25:34.6185999Z bfc5cca7d80e: Verifying Checksum +2022-12-09T17:25:34.6186341Z bfc5cca7d80e: Download complete +2022-12-09T17:25:34.6627434Z 7c62fb63f605: Verifying Checksum +2022-12-09T17:25:34.6629228Z 7c62fb63f605: Download complete +2022-12-09T17:25:34.8423112Z 09f325326117: Verifying Checksum +2022-12-09T17:25:34.8424383Z 09f325326117: Download complete +2022-12-09T17:25:35.0142784Z a73a0a50c4db: Verifying Checksum +2022-12-09T17:25:35.0143743Z a73a0a50c4db: Download complete +2022-12-09T17:25:35.2282893Z 0f68cc81f8f6: Verifying Checksum +2022-12-09T17:25:35.2283672Z 0f68cc81f8f6: Download complete +2022-12-09T17:25:35.8547685Z 61b6e3e25463: Verifying Checksum +2022-12-09T17:25:35.8547985Z 61b6e3e25463: Download complete +2022-12-09T17:25:36.3689873Z eff15d958d66: Pull complete +2022-12-09T17:25:38.9751393Z 923e91ae3a1b: Pull complete +2022-12-09T17:25:39.0574850Z 2aa5d3a4a151: Pull complete +2022-12-09T17:25:39.6785807Z bc64adf2d0b2: Pull complete +2022-12-09T17:25:39.7560781Z bfc5cca7d80e: Pull complete +2022-12-09T17:25:45.3145640Z 61b6e3e25463: Pull complete +2022-12-09T17:25:45.3626474Z 7c62fb63f605: Pull complete +2022-12-09T17:25:48.5182928Z 0f68cc81f8f6: Pull complete +2022-12-09T17:25:48.5924407Z 09f325326117: Pull complete +2022-12-09T17:25:48.6361139Z a73a0a50c4db: Pull complete +2022-12-09T17:25:48.6390662Z Digest: sha256:e56d7e4c5ac45aa2934b1d535f4c66769a442ef6538c7948f8b4e3b2950fd7b4 +2022-12-09T17:25:48.6435854Z Status: Downloaded newer image for ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:48.6436263Z ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:48.6444026Z ##[endgroup] +2022-12-09T17:25:48.6814585Z ##[group]Run actions/checkout@v3 +2022-12-09T17:25:48.6814842Z with: +2022-12-09T17:25:48.6815018Z ref: main +2022-12-09T17:25:48.6815204Z submodules: recursive +2022-12-09T17:25:48.6815442Z repository: octo-org/octo-template +2022-12-09T17:25:48.6815884Z token: *** +2022-12-09T17:25:48.6816068Z ssh-strict: true +2022-12-09T17:25:48.6816284Z persist-credentials: true +2022-12-09T17:25:48.6816500Z clean: true +2022-12-09T17:25:48.6816685Z fetch-depth: 1 +2022-12-09T17:25:48.6816872Z lfs: false +2022-12-09T17:25:48.6817076Z set-safe-directory: true +2022-12-09T17:25:48.6817275Z ##[endgroup] +2022-12-09T17:25:48.9194010Z Syncing repository: octo-org/octo-template +2022-12-09T17:25:48.9195798Z ##[group]Getting Git version info +2022-12-09T17:25:48.9196263Z Working directory is '/home/runner/work/octo-template/octo-template' +2022-12-09T17:25:48.9196777Z [command]/usr/bin/git version +2022-12-09T17:25:48.9267188Z git version 2.38.1 +2022-12-09T17:25:48.9293570Z ##[endgroup] +2022-12-09T17:25:48.9315385Z Temporarily overriding HOME='/home/runner/work/_temp/54730a3a-82b6-4069-a509-366e53e131cc' before making global git config changes +2022-12-09T17:25:48.9315845Z Adding repository directory to the temporary git global config as a safe directory +2022-12-09T17:25:48.9316365Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/octo-template/octo-template +2022-12-09T17:25:48.9362562Z Deleting the contents of '/home/runner/work/octo-template/octo-template' +2022-12-09T17:25:48.9366563Z ##[group]Initializing the repository +2022-12-09T17:25:48.9370913Z [command]/usr/bin/git init /home/runner/work/octo-template/octo-template +2022-12-09T17:25:48.9428579Z hint: Using 'master' as the name for the initial branch. This default branch name +2022-12-09T17:25:48.9429400Z hint: is subject to change. To configure the initial branch name to use in all +2022-12-09T17:25:48.9429828Z hint: of your new repositories, which will suppress this warning, call: +2022-12-09T17:25:48.9430089Z hint: +2022-12-09T17:25:48.9430525Z hint: git config --global init.defaultBranch +2022-12-09T17:25:48.9430769Z hint: +2022-12-09T17:25:48.9431094Z hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and +2022-12-09T17:25:48.9431510Z hint: 'development'. The just-created branch can be renamed via this command: +2022-12-09T17:25:48.9431770Z hint: +2022-12-09T17:25:48.9431994Z hint: git branch -m +2022-12-09T17:25:48.9442316Z Initialized empty Git repository in /home/runner/work/octo-template/octo-template/.git/ +2022-12-09T17:25:48.9454154Z [command]/usr/bin/git remote add origin https://github.com/octo-org/octo-template +2022-12-09T17:25:48.9490442Z ##[endgroup] +2022-12-09T17:25:48.9491112Z ##[group]Disabling automatic garbage collection +2022-12-09T17:25:48.9494676Z [command]/usr/bin/git config --local gc.auto 0 +2022-12-09T17:25:48.9524540Z ##[endgroup] +2022-12-09T17:25:48.9525308Z ##[group]Setting up auth +2022-12-09T17:25:48.9532488Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2022-12-09T17:25:48.9563906Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || : +2022-12-09T17:25:48.9857748Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2022-12-09T17:25:48.9892225Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || : +2022-12-09T17:25:49.0110192Z [command]/usr/bin/git config --local http.https://github.com/.extraheader AUTHORIZATION: basic *** +2022-12-09T17:25:49.0146631Z ##[endgroup] +2022-12-09T17:25:49.0147330Z ##[group]Fetching the repository +2022-12-09T17:25:49.0156010Z [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +refs/heads/main*:refs/remotes/origin/main* +refs/tags/main*:refs/tags/main* +2022-12-09T17:25:49.2837218Z remote: Enumerating objects: 3, done. +2022-12-09T17:25:49.2837524Z remote: Counting objects: 33% (1/3) +2022-12-09T17:25:49.2837809Z remote: Counting objects: 66% (2/3) +2022-12-09T17:25:49.2838044Z remote: Counting objects: 100% (3/3) +2022-12-09T17:25:49.2839733Z remote: Counting objects: 100% (3/3), done. +2022-12-09T17:25:49.2840661Z remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 +2022-12-09T17:25:49.2896737Z From https://github.com/octo-org/octo-template +2022-12-09T17:25:49.2897109Z * [new branch] main -> origin/main +2022-12-09T17:25:49.2924446Z ##[endgroup] +2022-12-09T17:25:49.2925129Z ##[group]Determining the checkout info +2022-12-09T17:25:49.2931526Z [command]/usr/bin/git branch --list --remote origin/main +2022-12-09T17:25:49.2958361Z origin/main +2022-12-09T17:25:49.2963283Z ##[endgroup] +2022-12-09T17:25:49.2964130Z ##[group]Checking out the ref +2022-12-09T17:25:49.2970560Z [command]/usr/bin/git checkout --progress --force -B main refs/remotes/origin/main +2022-12-09T17:25:49.3010381Z Switched to a new branch 'main' +2022-12-09T17:25:49.3014811Z branch 'main' set up to track 'origin/main'. +2022-12-09T17:25:49.3019861Z ##[endgroup] +2022-12-09T17:25:49.3022847Z ##[group]Setting up auth for fetching submodules +2022-12-09T17:25:49.3031486Z [command]/usr/bin/git config --global http.https://github.com/.extraheader AUTHORIZATION: basic *** +2022-12-09T17:25:49.3101009Z [command]/usr/bin/git config --global --unset-all url.https://github.com/.insteadOf +2022-12-09T17:25:49.3132496Z [command]/usr/bin/git config --global --add url.https://github.com/.insteadOf git@github.com: +2022-12-09T17:25:49.3159145Z ##[endgroup] +2022-12-09T17:25:49.3159671Z ##[group]Fetching submodules +2022-12-09T17:25:49.3163060Z [command]/usr/bin/git submodule sync --recursive +2022-12-09T17:25:49.3374628Z [command]/usr/bin/git -c protocol.version=2 submodule update --init --force --depth=1 --recursive +2022-12-09T17:25:49.3595435Z [command]/usr/bin/git submodule foreach --recursive git config --local gc.auto 0 +2022-12-09T17:25:49.3838526Z ##[endgroup] +2022-12-09T17:25:49.3839209Z ##[group]Persisting credentials for submodules +2022-12-09T17:25:49.3844491Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'url\.https\:\/\/github\.com\/\.insteadOf' && git config --local --unset-all 'url.https://github.com/.insteadOf' || : +2022-12-09T17:25:49.4113780Z [command]/usr/bin/git submodule foreach --recursive git config --local 'http.https://github.com/.extraheader' 'AUTHORIZATION: basic ***' && git config --local --show-origin --name-only --get-regexp remote.origin.url +2022-12-09T17:25:49.4324497Z [command]/usr/bin/git submodule foreach --recursive git config --local --add 'url.https://github.com/.insteadOf' 'git@github.com:' +2022-12-09T17:25:49.4536981Z ##[endgroup] +2022-12-09T17:25:49.4565161Z [command]/usr/bin/git log -1 --format='%H' +2022-12-09T17:25:49.4592051Z 'c85af0e5e5798047462143a13c1b455ee1275a64' +2022-12-09T17:25:49.4851246Z ##[group]Run actions/jekyll-build-pages@v1 +2022-12-09T17:25:49.4851491Z with: +2022-12-09T17:25:49.4851672Z source: . +2022-12-09T17:25:49.4851856Z destination: ./_site +2022-12-09T17:25:49.4852055Z future: false +2022-12-09T17:25:49.4852300Z build_revision: c85af0e5e5798047462143a13c1b455ee1275a64 +2022-12-09T17:25:49.4852525Z verbose: true +2022-12-09T17:25:49.4852887Z token: *** +2022-12-09T17:25:49.4853073Z ##[endgroup] +2022-12-09T17:25:49.5094807Z ##[command]/usr/bin/docker run --name ghcrioactionsjekyllbuildpagesv104_e36266 --label 290506 --workdir /github/workspace --rm -e "INPUT_SOURCE" -e "INPUT_DESTINATION" -e "INPUT_FUTURE" -e "INPUT_BUILD_REVISION" -e "INPUT_VERBOSE" -e "INPUT_TOKEN" -e "HOME" -e "GITHUB_JOB" -e "GITHUB_REF" -e "GITHUB_SHA" -e "GITHUB_REPOSITORY" -e "GITHUB_REPOSITORY_OWNER" -e "GITHUB_RUN_ID" -e "GITHUB_RUN_NUMBER" -e "GITHUB_RETENTION_DAYS" -e "GITHUB_RUN_ATTEMPT" -e "GITHUB_ACTOR" -e "GITHUB_TRIGGERING_ACTOR" -e "GITHUB_WORKFLOW" -e "GITHUB_HEAD_REF" -e "GITHUB_BASE_REF" -e "GITHUB_EVENT_NAME" -e "GITHUB_SERVER_URL" -e "GITHUB_API_URL" -e "GITHUB_GRAPHQL_URL" -e "GITHUB_REF_NAME" -e "GITHUB_REF_PROTECTED" -e "GITHUB_REF_TYPE" -e "GITHUB_WORKSPACE" -e "GITHUB_ACTION" -e "GITHUB_EVENT_PATH" -e "GITHUB_ACTION_REPOSITORY" -e "GITHUB_ACTION_REF" -e "GITHUB_PATH" -e "GITHUB_ENV" -e "GITHUB_STEP_SUMMARY" -e "GITHUB_STATE" -e "GITHUB_OUTPUT" -e "RUNNER_OS" -e "RUNNER_ARCH" -e "RUNNER_NAME" -e "RUNNER_TOOL_CACHE" -e "RUNNER_TEMP" -e "RUNNER_WORKSPACE" -e "ACTIONS_RUNTIME_URL" -e "ACTIONS_RUNTIME_TOKEN" -e "ACTIONS_CACHE_URL" -e "ACTIONS_ID_TOKEN_REQUEST_URL" -e "ACTIONS_ID_TOKEN_REQUEST_TOKEN" -e GITHUB_ACTIONS=true -e CI=true -v "/var/run/docker.sock":"/var/run/docker.sock" -v "/home/runner/work/_temp/_github_home":"/github/home" -v "/home/runner/work/_temp/_github_workflow":"/github/workflow" -v "/home/runner/work/_temp/_runner_file_commands":"/github/file_commands" -v "/home/runner/work/octo-template/octo-template":"/github/workspace" ghcr.io/actions/jekyll-build-pages:v1.0.4 +2022-12-09T17:25:50.5151506Z [33mConfiguration file: none[0m +2022-12-09T17:25:50.5313330Z Logging at level: debug +2022-12-09T17:25:50.5313941Z GitHub Pages: github-pages v227 +2022-12-09T17:25:50.5314484Z GitHub Pages: jekyll v3.9.2 +2022-12-09T17:25:50.5315560Z Theme: jekyll-theme-primer +2022-12-09T17:25:50.5316125Z Theme source: /usr/local/bundle/gems/jekyll-theme-primer-0.6.0 +2022-12-09T17:25:50.5316710Z Requiring: jekyll-github-metadata +2022-12-09T17:25:50.6063961Z To use retry middleware with Faraday v2.0+, install faraday-retry gem +2022-12-09T17:25:52.4164334Z Requiring: jekyll-seo-tag +2022-12-09T17:25:52.4165089Z Requiring: jekyll-coffeescript +2022-12-09T17:25:52.4166139Z Requiring: jekyll-commonmark-ghpages +2022-12-09T17:25:52.4166490Z Requiring: jekyll-gist +2022-12-09T17:25:52.4167025Z Requiring: jekyll-github-metadata +2022-12-09T17:25:52.4167363Z Requiring: jekyll-paginate +2022-12-09T17:25:52.4167663Z Requiring: jekyll-relative-links +2022-12-09T17:25:52.4167989Z Requiring: jekyll-optional-front-matter +2022-12-09T17:25:52.4168298Z Requiring: jekyll-readme-index +2022-12-09T17:25:52.4168589Z Requiring: jekyll-default-layout +2022-12-09T17:25:52.4168888Z Requiring: jekyll-titles-from-headings +2022-12-09T17:25:52.4169143Z GitHub Metadata: Initializing... +2022-12-09T17:25:52.4169392Z Source: /github/workspace/. +2022-12-09T17:25:52.4169651Z Destination: /github/workspace/./_site +2022-12-09T17:25:52.4169981Z Incremental build: disabled. Enable with --incremental +2022-12-09T17:25:52.4170230Z Generating... +2022-12-09T17:25:52.4183638Z Generating: JekyllOptionalFrontMatter::Generator finished in 0.000150897 seconds. +2022-12-09T17:25:52.4184136Z Generating: JekyllReadmeIndex::Generator finished in 0.00169567 seconds. +2022-12-09T17:25:52.4185038Z Generating: Jekyll::Paginate::Pagination finished in 4.8e-06 seconds. +2022-12-09T17:25:52.4185483Z Generating: JekyllRelativeLinks::Generator finished in 2.97e-05 seconds. +2022-12-09T17:25:52.4185914Z Generating: JekyllDefaultLayout::Generator finished in 7.7999e-05 seconds. +2022-12-09T17:25:52.4186258Z Requiring: kramdown-parser-gfm +2022-12-09T17:25:52.4186586Z Generating: JekyllTitlesFromHeadings::Generator finished in 0.008350253 seconds. +2022-12-09T17:25:52.4186888Z Rendering: assets/css/style.scss +2022-12-09T17:25:52.4187176Z Pre-Render Hooks: assets/css/style.scss +2022-12-09T17:25:52.4187437Z Rendering Markup: assets/css/style.scss +2022-12-09T17:25:52.4187672Z Rendering: README.md +2022-12-09T17:25:52.4187920Z Pre-Render Hooks: README.md +2022-12-09T17:25:52.4188141Z Rendering Markup: README.md +2022-12-09T17:25:52.4188360Z Rendering Layout: README.md +2022-12-09T17:25:52.4188568Z Layout source: theme +2022-12-09T17:25:52.4188886Z GitHub Metadata: Generating for octo-org/octo-template +2022-12-09T17:25:52.4189408Z GitHub Metadata: Calling @client.repository("octo-org/octo-template", {:accept=>"application/vnd.github.drax-preview+json"}) +2022-12-09T17:25:52.4189903Z GitHub Metadata: Calling @client.pages("octo-org/octo-template", {}) +2022-12-09T17:25:52.4190223Z Writing: /github/workspace/_site/assets/css/style.css +2022-12-09T17:25:52.4190520Z Writing: /github/workspace/_site/index.html +2022-12-09T17:25:52.4190772Z done in 1.524 seconds. +2022-12-09T17:25:52.4191074Z Auto-regeneration: disabled. Use --watch to enable. +2022-12-09T17:25:52.5460546Z ##[group]Run actions/upload-pages-artifact@v1 +2022-12-09T17:25:52.5460787Z with: +2022-12-09T17:25:52.5460968Z path: ./_site +2022-12-09T17:25:52.5461168Z name: github-pages +2022-12-09T17:25:52.5461361Z retention-days: 1 +2022-12-09T17:25:52.5461560Z ##[endgroup] +2022-12-09T17:25:52.5745795Z ##[group]Run chmod -c -R +rX . | while read line; do +2022-12-09T17:25:52.5746128Z [36;1mchmod -c -R +rX . | while read line; do[0m +2022-12-09T17:25:52.5746462Z [36;1m echo "::warning title=Invalid file permissions automatically fixed::$line"[0m +2022-12-09T17:25:52.5746740Z [36;1mdone[0m +2022-12-09T17:25:52.5746920Z [36;1mtar \[0m +2022-12-09T17:25:52.5747146Z [36;1m --dereference --hard-dereference \[0m +2022-12-09T17:25:52.5747410Z [36;1m --directory "$INPUT_PATH" \[0m +2022-12-09T17:25:52.5747668Z [36;1m -cvf "$RUNNER_TEMP/artifact.tar" \[0m +2022-12-09T17:25:52.5747896Z [36;1m --exclude=.git \[0m +2022-12-09T17:25:52.5748110Z [36;1m --exclude=.github \[0m +2022-12-09T17:25:52.5748352Z [36;1m .[0m +2022-12-09T17:25:52.5805770Z shell: /usr/bin/sh -e {0} +2022-12-09T17:25:52.5805980Z env: +2022-12-09T17:25:52.5806170Z INPUT_PATH: ./_site +2022-12-09T17:25:52.5806374Z ##[endgroup] +2022-12-09T17:25:52.5967973Z chmod: changing permissions of './_site': Operation not permitted +2022-12-09T17:25:52.5986749Z chmod: changing permissions of './_site/index.html': Operation not permitted +2022-12-09T17:25:52.5987217Z chmod: changing permissions of './_site/README.md': Operation not permitted +2022-12-09T17:25:52.5987625Z chmod: changing permissions of './_site/assets': Operation not permitted +2022-12-09T17:25:52.5988025Z chmod: changing permissions of './_site/assets/css': Operation not permitted +2022-12-09T17:25:52.5988455Z chmod: changing permissions of './_site/assets/css/style.css': Operation not permitted +2022-12-09T17:25:52.6003872Z ./ +2022-12-09T17:25:52.6004035Z ./index.html +2022-12-09T17:25:52.6004213Z ./README.md +2022-12-09T17:25:52.6004387Z ./assets/ +2022-12-09T17:25:52.6004556Z ./assets/css/ +2022-12-09T17:25:52.6004743Z ./assets/css/style.css +2022-12-09T17:25:52.6089697Z ##[group]Run actions/upload-artifact@main +2022-12-09T17:25:52.6089918Z with: +2022-12-09T17:25:52.6090104Z name: github-pages +2022-12-09T17:25:52.6090342Z path: /home/runner/work/_temp/artifact.tar +2022-12-09T17:25:52.6090677Z retention-days: 1 +2022-12-09T17:25:52.6090884Z if-no-files-found: warn +2022-12-09T17:25:52.6091085Z ##[endgroup] +2022-12-09T17:25:52.6745114Z With the provided path, there will be 1 file uploaded +2022-12-09T17:25:52.6748618Z Starting artifact upload +2022-12-09T17:25:52.6749367Z For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging +2022-12-09T17:25:52.6750012Z Artifact name is valid! +2022-12-09T17:25:52.7711407Z Container for artifact "github-pages" successfully created. Starting upload of file(s) +2022-12-09T17:25:52.8679144Z Total size of all the files uploaded is 12638 bytes +2022-12-09T17:25:52.8680162Z File upload process has finished. Finalizing the artifact upload +2022-12-09T17:25:52.8976033Z Artifact has been finalized. All files have been successfully uploaded! +2022-12-09T17:25:52.8976512Z +2022-12-09T17:25:52.8976816Z The raw size of all the files that were specified for upload is 92160 bytes +2022-12-09T17:25:52.8977329Z The size of all the files that were uploaded is 12638 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage +2022-12-09T17:25:52.8977612Z +2022-12-09T17:25:52.8978179Z Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads +2022-12-09T17:25:52.8978524Z +2022-12-09T17:25:52.8980509Z Artifact github-pages has been successfully uploaded! +2022-12-09T17:25:52.9084311Z Post job cleanup. +2022-12-09T17:25:53.0358449Z [command]/usr/bin/git version +2022-12-09T17:25:53.0407485Z git version 2.38.1 +2022-12-09T17:25:53.0465462Z Temporarily overriding HOME='/home/runner/work/_temp/52bccf8b-8b44-45e0-a383-0833ced20023' before making global git config changes +2022-12-09T17:25:53.0470560Z Adding repository directory to the temporary git global config as a safe directory +2022-12-09T17:25:53.0478850Z [command]/usr/bin/git config --global --add safe.directory /home/runner/work/octo-template/octo-template +2022-12-09T17:25:53.0517249Z [command]/usr/bin/git config --local --name-only --get-regexp core\.sshCommand +2022-12-09T17:25:53.0550835Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || : +2022-12-09T17:25:53.0769173Z [command]/usr/bin/git config --local --name-only --get-regexp http\.https\:\/\/github\.com\/\.extraheader +2022-12-09T17:25:53.0792441Z http.https://github.com/.extraheader +2022-12-09T17:25:53.0803756Z [command]/usr/bin/git config --local --unset-all http.https://github.com/.extraheader +2022-12-09T17:25:53.0838329Z [command]/usr/bin/git submodule foreach --recursive git config --local --name-only --get-regexp 'http\.https\:\/\/github\.com\/\.extraheader' && git config --local --unset-all 'http.https://github.com/.extraheader' || : +2022-12-09T17:25:53.1274888Z Cleaning up orphan processes +`; diff --git a/plugins/github-actions/src/__fixtures__/list-workflow-runs.json b/plugins/github-actions/src/__fixtures__/list-workflow-runs.json new file mode 100644 index 0000000000..4d1e1223ce --- /dev/null +++ b/plugins/github-actions/src/__fixtures__/list-workflow-runs.json @@ -0,0 +1,223 @@ +{ + "total_count": 1, + "workflow_runs": [ + { + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "master", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "run_number": 562, + "event": "push", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "run_attempt": 1, + "run_started_at": "2020-01-22T19:33:08Z", + "triggering_actor": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } + } + ] +} diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 5e0a5f3e15..f55cad8424 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -94,7 +94,7 @@ describe('', () => { ); it('renders a table with a row for each workflow', async () => { - const subject = await renderSubject(); + const subject = renderSubject(); workflowRuns.forEach(run => { expect(subject.getByText(run.message)).toBeInTheDocument(); @@ -102,7 +102,7 @@ describe('', () => { }); it('renders a workflow row correctly', async () => { - const subject = await renderSubject(); + const subject = renderSubject(); const [run] = workflowRuns; expect(subject.getByText(run.message).closest('a')).toHaveAttribute( 'href', diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index f76d88bda7..9c3d9c85e4 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-github-deployments +## 0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + ## 0.1.46-next.0 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index c673adc712..17d6239b90 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.46-next.0", + "version": "0.1.46-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index f87eef712c..35aa080016 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-github-issues +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 0.2.4-next.0 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 8a12fd2153..574968d61a 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.4-next.0", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 5c71016753..8dd45cd956 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/theme@0.2.16 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 7558d60649..163b7a1967 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.9-next.0", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index c7e895315a..4ade8515ff 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-gitops-profiles +## 0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.3.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.32 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index b485aea867..f43e7bb14b 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.32", + "version": "0.3.33-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index a030870317..01037953b0 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-gocd +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.1.21-next.0 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 8988f26b93..f89a11047d 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.21-next.0", + "version": "0.1.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index f14c0602d0..68d6fa8e25 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-graphiql +## 0.2.47-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.2.47-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.2.46 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 92c89dda60..15d15a38ca 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.46", + "version": "0.2.47-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 7467f7a0bf..28efff9546 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-graphql-backend +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.1 + +## 0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-catalog-graphql@0.3.18-next.0 + ## 0.1.32-next.0 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 7e351e5db0..0f44248997 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.32-next.0", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/.eslintrc.js b/plugins/graphql-voyager/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/graphql-voyager/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md new file mode 100644 index 0000000000..3712169ea1 --- /dev/null +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -0,0 +1,16 @@ +# @backstage/plugin-graphql-voyager + +## 0.1.0-next.0 + +### Minor Changes + +- d1fb4b7bf1: Add the new GraphQL Voyager tool as a plugin for backstage, expose necessary API and components needed for it. + + For more information on how to use this plugin and configure it, please navigate to the [README](https://github.com/backstage/backstage/tree/master/plugins/graphql-voyager/README.md) of the plugin. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 diff --git a/plugins/graphql-voyager/README.md b/plugins/graphql-voyager/README.md new file mode 100644 index 0000000000..2c903cd9e5 --- /dev/null +++ b/plugins/graphql-voyager/README.md @@ -0,0 +1,76 @@ +# graphql-voyager + +Welcome to the graphql-voyager plugin! + +Presents a graph structure of your entire GraphQL API, with tabs for multiple API urls: +![](./src/assets/plugin.png) + +## Getting started + +### Installing + +To get started, first install the plugin with the following command: + +```bash +# From your Backstage root directory +yarn add --cwd packages/app @backstage/plugin-graphql-voyager +``` + +### Adding the page + +In order to be able to navigate to the graphQL voyager page, a new route needs to be added to the app. This can be done in the following way: + +```tsx +// packages/app/App.tsx + + import { GraphQLVoyagerPage } from '@backstage/plugin-graphql-voyager'; + + const routes = ( + + }/> +``` + +### Configuration + +In order for the plugin to function correctly. GraphQL endpoints need to be added / configured through the GraphQLVoyager API. This can be done by implementing the `graphQlVoyagerApiRef` exported by this plugin. + +Add your own configuration to the `packages/app/src/apis.ts` file the following way: + +```ts +import { identityApiRef } from '@backstage/core-plugin-api'; +import { GraphQLVoyagerEndpoints } from '@backstage/plugin-graphql-voyager'; + +export const apis: AnyApiFactory[] = [ + createApiFactory({ + api: graphQlVoyagerApiRef, + deps: { identityApi: identityApiRef }, + factory: ({ identityApiRef }) => { + return GraphQLVoyagerEndpoints.from([ + { + id: `graphql-voyager-endpoint-id`, + title: 'endpoint-title', + introspectionErrorMessage: + 'Unable to perform introspection, make sure you are on the correct environment.', + introspection: async (query: any) => { + const token = 'someSecretJWTComingFromIdentityApiRef'; + + const res = await fetch('graphQLEndpoint', { + method: 'POST', + body: JSON.stringify({ query }), + headers: { + 'Content-Type': 'application/json', + Authorization: token, + }, + }); + + return res.json(); + }, + voyagerProps: { + hideDocs: true, + }, + }, + ]); + }, + }), +]; +``` diff --git a/plugins/graphql-voyager/api-report.md b/plugins/graphql-voyager/api-report.md new file mode 100644 index 0000000000..9b488f9356 --- /dev/null +++ b/plugins/graphql-voyager/api-report.md @@ -0,0 +1,71 @@ +## API Report File for "@backstage/plugin-graphql-voyager" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiRef } from '@backstage/core-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +// @public (undocumented) +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +// @public (undocumented) +export const graphQlVoyagerApiRef: ApiRef; + +// @public (undocumented) +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +// @public (undocumented) +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + // (undocumented) + static from(endpoints: GraphQLVoyagerEndpoint[]): GraphQLVoyagerEndpoints; + // (undocumented) + getEndpoints(): Promise; +} + +// @public (undocumented) +export const GraphqlVoyagerPage: ( + props: GraphQLVoyagerPageProps, +) => JSX.Element; + +// @public (undocumented) +export type GraphQLVoyagerPageProps = { + title?: string; +}; + +// @public (undocumented) +export const graphqlVoyagerPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; + +// @public (undocumented) +export const introspectionQuery: string; + +// @public (undocumented) +export const Router: (props: GraphQLVoyagerPageProps) => JSX.Element; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json new file mode 100644 index 0000000000..b20d045640 --- /dev/null +++ b/plugins/graphql-voyager/package.json @@ -0,0 +1,53 @@ +{ + "name": "@backstage/plugin-graphql-voyager", + "description": "Backstage plugin for GraphQL Voyager", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "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" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "graphql-voyager": "^1.0.0-rc.31", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/graphql-voyager/src/assets/plugin.png b/plugins/graphql-voyager/src/assets/plugin.png new file mode 100644 index 0000000000..602c7abde3 Binary files /dev/null and b/plugins/graphql-voyager/src/assets/plugin.png differ diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx new file mode 100644 index 0000000000..76ccbd9965 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright 2023 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 { renderInTestApp } from '@backstage/test-utils'; +import { GraphQLVoyagerBrowser } from './GraphQLVoyagerBrowser'; + +jest.mock('graphql-voyager', () => ({ Voyager: () => '' })); + +describe('GraphQLVoyagerBrowser', () => { + it('should render error text if there are no endpoints', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('No endpoints available')).toBeInTheDocument(); + }); + + it('should render endpoint tabs', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Endpoint A')).toBeInTheDocument(); + expect(rendered.getByText('Endpoint B')).toBeInTheDocument(); + }); + + it('Should render the introspection error message when introspection fails', async () => { + const rendered = await renderInTestApp( + , + ); + + expect(rendered.getByText('Failed to introspect A')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx new file mode 100644 index 0000000000..d2f9262983 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -0,0 +1,107 @@ +/* + * Copyright 2023 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 { + GraphQLVoyagerEndpoint, + introspectionQuery, +} from '../../lib/api/types'; +import { useState } from 'react'; +import { makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; +import React, { Suspense } from 'react'; +import { BackstageTheme } from '@backstage/theme'; +import { Content, ErrorPanel, Progress } from '@backstage/core-components'; +import { Voyager } from 'graphql-voyager'; +import useAsync from 'react-use/lib/useAsync'; + +const useStyles = makeStyles(() => ({ + root: { + height: '100%', + display: 'flex', + flexFlow: 'column nowrap', + }, +})); + +type GraphQLVoyagerBrowserProps = { + endpoints: GraphQLVoyagerEndpoint[]; +}; + +const NoEndpoints = () => { + return No endpoints available; +}; + +const VoyagerBrowserContent = ({ + endpoint, +}: { + endpoint: GraphQLVoyagerEndpoint; +}) => { + const { id, introspection, introspectionErrorMessage, voyagerProps } = + endpoint; + const { value, loading, error } = useAsync( + () => introspection(introspectionQuery), + [endpoint], + ); + + if (loading) { + return ; + } else if (error) { + return ; + } + return value.data ? ( + + ) : ( + + {introspectionErrorMessage} + + ); +}; + +const VoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const { endpoints } = props; + const [tabIndex, setTabIndex] = useState(0); + const classes = useStyles(); + + return ( +
    + }> + setTabIndex(value)} + indicatorColor="primary" + > + {endpoints.map(({ title, id }, index) => ( + + ))} + + + + + +
    + ); +}; + +/** @public */ +export const GraphQLVoyagerBrowser = (props: GraphQLVoyagerBrowserProps) => { + const hasEndpoints = checkEndpoints(props); + + if (!hasEndpoints) { + return ; + } + return ; +}; + +function checkEndpoints(props: GraphQLVoyagerBrowserProps) { + return props.endpoints.length; +} diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts new file mode 100644 index 0000000000..3beb0ccd95 --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx new file mode 100644 index 0000000000..67c257be2b --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.test.tsx @@ -0,0 +1,60 @@ +/* + * Copyright 2023 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 { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; + +import { GraphQLVoyagerPage } from './GraphQLVoyagerPage'; +import { GraphQLVoyagerApi, graphQlVoyagerApiRef } from '../../lib/api'; + +jest.mock('../GraphQLVoyagerBrowser', () => ({ + GraphQLVoyagerBrowser: () => '', +})); + +describe('GraphQLVoyagerPage', () => { + it('should show error when no endpoints are loaded', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + throw new Error('No endpoints'); + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect(rendered.getByText('Error: No endpoints')).toBeInTheDocument(); + }); + + it('should show GraphQLVoyagerBrowser', async () => { + const loadingApi: GraphQLVoyagerApi = { + async getEndpoints() { + return []; + }, + }; + + const rendered = await renderInTestApp( + + + , + ); + + expect(rendered.getByText('Welcome to Voyager!')).toBeInTheDocument(); + expect(rendered.getByText('')).toBeInTheDocument(); + }); +}); diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx new file mode 100644 index 0000000000..f3c4f70b4f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/GraphQLVoyagerPage.tsx @@ -0,0 +1,62 @@ +/* + * Copyright 2023 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 { + Header, + Page, + Content, + Progress, + ErrorPanel, +} from '@backstage/core-components'; +import { useApi } from '@backstage/core-plugin-api'; +import 'graphql-voyager/dist/voyager.css'; +import { graphQlVoyagerApiRef } from '../../lib/api'; +import useAsync from 'react-use/lib/useAsync'; +import { GraphQLVoyagerBrowser } from '../GraphQLVoyagerBrowser'; + +/** @public */ +export type GraphQLVoyagerPageProps = { + title?: string; +}; + +const VoyagerContent = () => { + const graphQLVoyagerApi = useApi(graphQlVoyagerApiRef); + + const { value, loading, error } = useAsync(() => + graphQLVoyagerApi.getEndpoints(), + ); + + if (loading) { + return ; + } else if (error) { + return ; + } + return ; +}; + +/** @public */ +export const GraphQLVoyagerPage = (props: GraphQLVoyagerPageProps) => { + const { title = 'Welcome to Voyager!' } = props; + + return ( + +
    + + + + + ); +}; diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts new file mode 100644 index 0000000000..5ee042fd5f --- /dev/null +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; diff --git a/plugins/graphql-voyager/src/components/index.ts b/plugins/graphql-voyager/src/components/index.ts new file mode 100644 index 0000000000..76c4229839 --- /dev/null +++ b/plugins/graphql-voyager/src/components/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerPage'; +export * from './GraphQLVoyagerBrowser'; diff --git a/plugins/graphql-voyager/src/index.ts b/plugins/graphql-voyager/src/index.ts new file mode 100644 index 0000000000..9e314c2eef --- /dev/null +++ b/plugins/graphql-voyager/src/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin, GraphqlVoyagerPage } from './plugin'; +export { GraphQLVoyagerPage as Router } from './components'; +export type { GraphQLVoyagerPageProps } from './components'; +export * from './lib/api'; diff --git a/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts new file mode 100644 index 0000000000..4d08ffbce3 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/GraphQLVoyagerEndpoints.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 { GraphQLVoyagerApi, GraphQLVoyagerEndpoint } from './types'; + +/** @public */ +export class GraphQLVoyagerEndpoints implements GraphQLVoyagerApi { + private constructor(private readonly endpoints: GraphQLVoyagerEndpoint[]) {} + + static from(endpoints: GraphQLVoyagerEndpoint[]) { + return new GraphQLVoyagerEndpoints(endpoints); + } + + async getEndpoints() { + return this.endpoints; + } +} diff --git a/plugins/graphql-voyager/src/lib/api/index.ts b/plugins/graphql-voyager/src/lib/api/index.ts new file mode 100644 index 0000000000..c52eedafb7 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './GraphQLVoyagerEndpoints'; +export * from './types'; diff --git a/plugins/graphql-voyager/src/lib/api/types.ts b/plugins/graphql-voyager/src/lib/api/types.ts new file mode 100644 index 0000000000..08e6f13923 --- /dev/null +++ b/plugins/graphql-voyager/src/lib/api/types.ts @@ -0,0 +1,141 @@ +/* + * Copyright 2023 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 { createApiRef } from '@backstage/core-plugin-api'; +import { VoyagerDisplayOptions } from 'graphql-voyager/typings/components/Voyager'; +import { WorkerCallback } from 'graphql-voyager/typings/utils/types'; + +/** @public */ +export type GraphQLVoyagerEndpoint = { + id: string; + title: string; + introspection: (body: any) => Promise; + introspectionErrorMessage: string; + voyagerProps?: { + displayOptions?: VoyagerDisplayOptions; + hideDocs?: boolean; + hideSettings?: boolean; + workerURI?: string; + loadWorker?: WorkerCallback; + }; +}; + +/** @public */ +export type GraphQLVoyagerApi = { + getEndpoints(): Promise; +}; + +/** @public */ +export const graphQlVoyagerApiRef = createApiRef({ + id: 'plugin.graphqlvoyager.api', +}); + +/** @public */ +export const introspectionQuery: string = `query IntrospectionQuery { + __schema { + + queryType { name } + mutationType { name } + subscriptionType { name } + types { + ...FullType + } + directives { + name + description + + locations + args { + ...InputValue + } + } + } + } + + fragment FullType on __Type { + kind + name + description + + fields(includeDeprecated: true) { + name + description + args { + ...InputValue + } + type { + ...TypeRef + } + isDeprecated + deprecationReason + } + inputFields { + ...InputValue + } + interfaces { + ...TypeRef + } + enumValues(includeDeprecated: true) { + name + description + isDeprecated + deprecationReason + } + possibleTypes { + ...TypeRef + } + } + + fragment InputValue on __InputValue { + name + description + type { ...TypeRef } + defaultValue + + + } + + fragment TypeRef on __Type { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + ofType { + kind + name + } + } + } + } + } + } + } + }`; diff --git a/plugins/graphql-voyager/src/plugin.test.ts b/plugins/graphql-voyager/src/plugin.test.ts new file mode 100644 index 0000000000..df7acc7143 --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { graphqlVoyagerPlugin } from './plugin'; + +describe('graphql-voyager', () => { + it('should export plugin', () => { + expect(graphqlVoyagerPlugin).toBeDefined(); + }); +}); diff --git a/plugins/graphql-voyager/src/plugin.ts b/plugins/graphql-voyager/src/plugin.ts new file mode 100644 index 0000000000..bd33209a1d --- /dev/null +++ b/plugins/graphql-voyager/src/plugin.ts @@ -0,0 +1,38 @@ +/* + * Copyright 2023 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 { + createPlugin, + createRoutableExtension, +} from '@backstage/core-plugin-api'; + +import { rootRouteRef } from './routes'; + +/** @public */ +export const graphqlVoyagerPlugin = createPlugin({ + id: 'graphql-voyager', + routes: { + root: rootRouteRef, + }, +}); + +/** @public */ +export const GraphqlVoyagerPage = graphqlVoyagerPlugin.provide( + createRoutableExtension({ + name: 'GraphqlVoyagerPage', + component: () => import('./components').then(m => m.GraphQLVoyagerPage), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/graphql-voyager/src/routes.ts b/plugins/graphql-voyager/src/routes.ts new file mode 100644 index 0000000000..12f06c1cb5 --- /dev/null +++ b/plugins/graphql-voyager/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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 { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'graphql-voyager', +}); diff --git a/plugins/graphql-voyager/src/setupTests.ts b/plugins/graphql-voyager/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/graphql-voyager/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index b06d9b7a5c..400ca51ae9 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-home +## 0.4.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.4.31-next.1 + +### Patch Changes + +- 3d1d867d42: Fixed regression that caused the `WelcomeTitle` to not be the right size when passed to the `title` property of the `
    ` component. A Storybook entry was also added for the `WelcomeTitle` +- c553a625d2: remove unused plugin-stack-overflow dependency +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.4.31-next.0 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 39d9b68aaf..6923b87c83 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.31-next.0", + "version": "0.4.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index ec39edeca1..a12bd0a010 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-ilert +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.4-next.0 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 53ab674dc4..757b91f78e 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.2.4-next.0", + "version": "0.2.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index e35e69b2d5..00f1cdfe1b 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-jenkins-backend +## 0.1.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + - @backstage/plugin-permission-common@0.7.3 + +## 0.1.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-jenkins-common@0.1.13-next.0 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.32-next.0 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 7880f391e0..d3107cba77 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.32-next.0", + "version": "0.1.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 71719e20e2..75a1470ed0 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-jenkins-common +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index c2d15a7da6..b37d1cfb8d 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.13-next.0", + "version": "0.1.13-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 086f7b354a..291f175013 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-jenkins +## 0.7.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-jenkins-common@0.1.13-next.1 + +## 0.7.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-jenkins-common@0.1.13-next.0 + ## 0.7.14-next.0 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index da7b46af08..d2c629136b 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.7.14-next.0", + "version": "0.7.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index fe39a7f219..262cca0397 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-kafka-backend +## 0.2.35-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.35-next.0 ### Patch Changes diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index 20c8260b52..a748a543d9 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-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 { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; +// @alpha +export const kafkaPlugin: () => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 172b4b70d8..f0c8d10bde 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,14 +1,15 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.35-next.0", + "version": "0.2.35-next.2", "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" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -26,7 +27,7 @@ "configSchema": "config.d.ts", "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -35,6 +36,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -54,6 +56,7 @@ }, "files": [ "dist", - "config.d.ts" + "config.d.ts", + "alpha" ] } diff --git a/plugins/kafka-backend/src/index.ts b/plugins/kafka-backend/src/index.ts index 70b7fb45a4..2000c8b89a 100644 --- a/plugins/kafka-backend/src/index.ts +++ b/plugins/kafka-backend/src/index.ts @@ -22,3 +22,4 @@ export type { RouterOptions } from './service/router'; export { createRouter } from './service/router'; +export { kafkaPlugin } from './plugin'; diff --git a/plugins/kafka-backend/src/plugin.ts b/plugins/kafka-backend/src/plugin.ts new file mode 100644 index 0000000000..2442eddbaa --- /dev/null +++ b/plugins/kafka-backend/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Kafka backend plugin. + * + * @alpha + */ +export const kafkaPlugin = createBackendPlugin({ + pluginId: 'kafka', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, logger, httpRouter }) { + httpRouter.use( + await createRouter({ config, logger: loggerToWinstonLogger(logger) }), + ); + }, + }); + }, +}); diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index f5833782df..74d5b82c97 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-kafka +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.15-next.0 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 40b9d5a8d0..546cf976d5 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.3.15-next.0", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 8fefe5f133..a8726b238a 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-kubernetes-backend +## 0.9.3-next.2 + +### Patch Changes + +- 7ff81f7692: Kubernetes proxy endpoint now accepts content types that are not json +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## 0.9.3-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-kubernetes-common@0.6.0-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 0.9.3-next.0 ### Patch Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 4ec043a8f9..006f980c56 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -141,7 +141,7 @@ export class GoogleServiceAccountAuthTranslator ): Promise; } -// @alpha +// @public export const HEADER_KUBERNETES_CLUSTER: string; // @alpha (undocumented) diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 0049aa6256..002a5e2651 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.9.3-next.0", + "version": "0.9.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,7 +36,6 @@ "dependencies": { "@azure/identity": "^2.0.4", "@backstage/backend-common": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", @@ -66,6 +65,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/aws4": "^1.5.1", "@types/http-proxy-middleware": "^0.19.3", diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts index 2766f9abfc..cc2dea26c0 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts @@ -31,6 +31,10 @@ import { import { KubernetesBuilder } from './KubernetesBuilder'; import { KubernetesFanOutHandler } from './KubernetesFanOutHandler'; import { CatalogApi } from '@backstage/catalog-client'; +import { HEADER_KUBERNETES_CLUSTER } from './KubernetesProxy'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { rest } from 'msw'; describe('KubernetesBuilder', () => { let app: express.Express; @@ -267,4 +271,65 @@ describe('KubernetesBuilder', () => { expect(response.status).toEqual(200); }); }); + + describe('post /proxy', () => { + const worker = setupServer(); + setupRequestMockHandlers(worker); + + beforeEach(() => { + worker.use( + rest.post('https://localhost:1234/api/v1/namespaces', (req, res, ctx) => + req + .arrayBuffer() + .then(body => + res( + ctx.set('content-type', `${req.headers.get('content-type')}`), + ctx.body(body), + ), + ), + ), + ); + }); + + it('returns the given request body', async () => { + const requestBody = { + kind: 'Namespace', + apiVersion: 'v1', + metadata: { + name: 'new-ns', + }, + }; + + const proxyEndpointRequest = request(app) + .post('/proxy/api/v1/namespaces') + .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') + .send(requestBody); + + worker.use(rest.all(proxyEndpointRequest.url, req => req.passthrough())); + + const response = await proxyEndpointRequest; + + expect(response.body).toStrictEqual(requestBody); + }); + + it('supports yaml content type', async () => { + const requestBody = `--- +kind: Namespace +apiVersion: v1 +metadata: + name: new-ns +`; + + const proxyEndpointRequest = request(app) + .post('/proxy/api/v1/namespaces') + .set(HEADER_KUBERNETES_CLUSTER, 'some-cluster') + .set('content-type', 'application/yaml') + .send(requestBody); + + worker.use(rest.all(proxyEndpointRequest.url, req => req.passthrough())); + + const response = await proxyEndpointRequest; + expect(response.text).toEqual(requestBody); + }); + }); }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 1e7b704ec5..92773ece6d 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -265,6 +265,7 @@ export class KubernetesBuilder { ): express.Router { const logger = this.env.logger; const router = Router(); + router.use('/proxy', proxy.createRequestHandler()); router.use(express.json()); // @deprecated @@ -297,8 +298,6 @@ export class KubernetesBuilder { }); }); - router.use('/proxy', proxy.createRequestHandler()); - addResourceRoutesToRouter(router, catalogApi, objectsProvider); return router; diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index 9d88d2ab84..cb36c647ac 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -32,7 +32,7 @@ export const APPLICATION_JSON: string = 'application/json'; /** * The header that is used to specify the cluster name. * - * @alpha + * @public */ export const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster'; diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index ec5b17df99..cd4df4d54a 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-kubernetes-common +## 0.6.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + +## 0.6.0-next.1 + +### Patch Changes + +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/catalog-model@1.1.6-next.0 + ## 0.6.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index 23dd9eeae5..4a4e2a30bf 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.6.0-next.0", + "version": "0.6.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index b5d62408ad..e30b168693 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-kubernetes +## 0.7.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-kubernetes-common@0.6.0-next.2 + +## 0.7.8-next.1 + +### Patch Changes + +- 145a79a15b: Condenses kubernetes ui plugin to fit more onscreen and increase visibility +- 628e2bd89a: Updated dependency `@kubernetes/client-node` to `0.18.1`. +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-kubernetes-common@0.6.0-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.7.8-next.0 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 96a369dccf..e51726b296 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.7.8-next.0", + "version": "0.7.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-backend/.eslintrc.js b/plugins/lighthouse-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/lighthouse-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md new file mode 100644 index 0000000000..d64d035fa3 --- /dev/null +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -0,0 +1,18 @@ +# @backstage/plugin-lighthouse-backend + +## 0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce Lighthouse Backend Plugin to run scheduled Lighthouse Audits + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 diff --git a/plugins/lighthouse-backend/README.md b/plugins/lighthouse-backend/README.md new file mode 100644 index 0000000000..8ae737725c --- /dev/null +++ b/plugins/lighthouse-backend/README.md @@ -0,0 +1,70 @@ +# Lighthouse Backend + +Lighthouse Backend allows you to run scheduled lighthouse Tests for each Website with the annotation `lighthouse.com/website-url`. + +## Setup + +1. Install the plugin using: + +```bash +# From your Backstage root directory +yarn add --cwd packages/backend @backstage/lighthouse-backend +``` + +2. Create a `lighthouse.ts` file inside `packages/backend/src/plugins/`: + +```typescript +import { Router } from 'express'; +import { createScheduler } from '@backstage/plugin-lighthouse-backend'; +import { PluginEnvironment } from '../types'; +import { CatalogClient } from '@backstage/catalog-client'; + +export default async function createPlugin(env: PluginEnvironment) { + const { logger, scheduler, config } = env; + + const catalogClient = new CatalogClient({ + discoveryApi: env.discovery, + }); + + await createScheduler({ logger, scheduler, config, catalogClient }); +} +``` + +3. Modify your `packages/backend/src/index.ts` to include: + +```diff + ... + + import { Config } from '@backstage/config'; + import app from './plugins/app'; ++import lighthouse from './plugins/lighthouse'; + import scaffolder from './plugins/scaffolder'; + + ... + + async function main() { + + ... + + const authEnv = useHotMemoize(module, () => createEnv('auth')); ++ const lighthouseEnv = useHotMemoize(module, () => createEnv('lighthouse')); + const proxyEnv = useHotMemoize(module, () => createEnv('proxy')); + + ... + + const apiRouter = Router(); + apiRouter.use('/catalog', await catalog(catalogEnv)); + apiRouter.use('/scaffolder', await scaffolder(scaffolderEnv)); + ++ await lighthouse(lighthouseEnv) +``` + +## Configuration + +You can define how often and when the scheduler should run the audits: + +```yaml +lighthouse: + schedule: + days: 1 +``` diff --git a/plugins/lighthouse-backend/api-report.md b/plugins/lighthouse-backend/api-report.md new file mode 100644 index 0000000000..a91e47dfc5 --- /dev/null +++ b/plugins/lighthouse-backend/api-report.md @@ -0,0 +1,29 @@ +## API Report File for "@backstage/plugin-lighthouse-backend" + +> 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 { Config } from '@backstage/config'; +import { Logger } from 'winston'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; + +// @public (undocumented) +export interface CreateLighthouseSchedulerOptions { + // (undocumented) + catalogClient: CatalogClient; + // (undocumented) + config: Config; + // (undocumented) + logger: Logger; + // (undocumented) + scheduler?: PluginTaskScheduler; +} + +// @public (undocumented) +export function createScheduler( + options: CreateLighthouseSchedulerOptions, +): Promise; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json new file mode 100644 index 0000000000..60b8570481 --- /dev/null +++ b/plugins/lighthouse-backend/package.json @@ -0,0 +1,53 @@ +{ + "name": "@backstage/plugin-lighthouse-backend", + "description": "Backend functionalities for lighthouse", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/lighthouse-backend" + }, + "keywords": [ + "lighthouse" + ], + "files": [ + "dist" + ], + "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" + }, + "bugs": { + "url": "https://github.com/backstage/backstage/issues" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-tasks": "workspace:^", + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-lighthouse-common": "workspace:^", + "@backstage/types": "workspace:^", + "winston": "^3.2.1" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/plugins/lighthouse-backend/src/config.ts b/plugins/lighthouse-backend/src/config.ts new file mode 100644 index 0000000000..bea1c35661 --- /dev/null +++ b/plugins/lighthouse-backend/src/config.ts @@ -0,0 +1,68 @@ +/* + * 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 { Config } from '@backstage/config'; +import { HumanDuration as HumanDuration } from '@backstage/types'; + +export interface LighthouseAuditScheduleConfig { + schedule: HumanDuration; + timeout: HumanDuration; + auditDetail: HumanDuration; +} + +/** @public */ +export type LighthouseAuditSchedule = { + getSchedule: () => HumanDuration; + getTimeout: () => HumanDuration; +}; + +/** @public */ +export class LighthouseAuditScheduleImpl implements LighthouseAuditSchedule { + static fromConfig(config: Config) { + const lighthouse = config.getOptionalConfig('lighthouse'); + + let schedule: HumanDuration = { days: 1 }; + let timeout: HumanDuration = {}; + + if (lighthouse) { + const scheduleConfig = lighthouse.getOptionalConfig('schedule'); + const timeoutConfig = lighthouse.getOptionalConfig('timeout'); + + if (scheduleConfig) { + schedule = scheduleConfig as HumanDuration; + } + + if (timeoutConfig) { + timeout = timeoutConfig as HumanDuration; + } + } + + return new LighthouseAuditScheduleImpl(schedule, timeout); + } + + constructor( + private schedule: HumanDuration, + private timeout: HumanDuration, + ) {} + + getSchedule(): HumanDuration { + return this.schedule; + } + + getTimeout(): HumanDuration { + return this.timeout; + } +} diff --git a/plugins/lighthouse-backend/src/index.ts b/plugins/lighthouse-backend/src/index.ts new file mode 100644 index 0000000000..ee878b9214 --- /dev/null +++ b/plugins/lighthouse-backend/src/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 * from './service/plugin'; diff --git a/plugins/lighthouse-backend/src/service/EntitiesLoader.ts b/plugins/lighthouse-backend/src/service/EntitiesLoader.ts new file mode 100644 index 0000000000..fe9aab48cc --- /dev/null +++ b/plugins/lighthouse-backend/src/service/EntitiesLoader.ts @@ -0,0 +1,32 @@ +/* + * 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, + CATALOG_FILTER_EXISTS, +} from '@backstage/catalog-client'; + +export async function loadLighthouseEntities(catalogClient: CatalogClient) { + const filter: Record = { + kind: 'Component', + 'spec.type': 'website', + ['lighthouse.com/website-url']: CATALOG_FILTER_EXISTS, + }; + + return await catalogClient.getEntities({ + filter: [filter], + }); +} diff --git a/plugins/lighthouse-backend/src/service/plugin.ts b/plugins/lighthouse-backend/src/service/plugin.ts new file mode 100644 index 0000000000..8e8952a3d6 --- /dev/null +++ b/plugins/lighthouse-backend/src/service/plugin.ts @@ -0,0 +1,128 @@ +/* + * 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 { Logger } from 'winston'; +import { PluginTaskScheduler } from '@backstage/backend-tasks'; +import { + CATALOG_FILTER_EXISTS, + CatalogClient, +} from '@backstage/catalog-client'; +import { Config } from '@backstage/config'; +import { LighthouseRestApi } from '@backstage/plugin-lighthouse-common'; +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { LighthouseAuditScheduleImpl } from '../config'; + +/** @public **/ +export interface CreateLighthouseSchedulerOptions { + logger: Logger; + config: Config; + scheduler?: PluginTaskScheduler; + catalogClient: CatalogClient; +} + +/** @public **/ +export async function createScheduler( + options: CreateLighthouseSchedulerOptions, +) { + const { logger, scheduler, catalogClient, config } = options; + const lighthouseApi = LighthouseRestApi.fromConfig(config); + + const lighthouseAuditConfig = LighthouseAuditScheduleImpl.fromConfig(config); + const formFactorToScreenEmulationMap = { + // the default is mobile, so no need to override + mobile: undefined, + // Values from lighthouse's cli "desktop" preset + // https://github.com/GoogleChrome/lighthouse/blob/a6738e0033e7e5ca308b97c1c36f298b7d399402/lighthouse-core/config/constants.js#L71-L77 + desktop: { + mobile: false, + width: 1350, + height: 940, + deviceScaleFactor: 1, + disabled: false, + }, + }; + + logger.info( + `Running with Scheduler Config ${JSON.stringify( + lighthouseAuditConfig.getSchedule(), + )} and timeout ${JSON.stringify(lighthouseAuditConfig.getTimeout())}`, + ); + + if (scheduler) { + await scheduler.scheduleTask({ + id: 'lighthouse_audit', + frequency: lighthouseAuditConfig.getSchedule(), + timeout: lighthouseAuditConfig.getTimeout(), + initialDelay: { minutes: 15 }, + fn: async () => { + const filter: Record = { + kind: 'Component', + 'spec.type': 'website', + ['metadata.annotations.lighthouse.com/website-url']: + CATALOG_FILTER_EXISTS, + }; + + logger.info('Running Lighthouse Audit Task'); + + const websitesWithUrl = await catalogClient.getEntities({ + filter: [filter], + }); + + let index = 0; + for (const entity of websitesWithUrl.items) { + const websiteUrl = + entity.metadata.annotations?.['lighthouse.com/website-url'] ?? ''; + + if (!websiteUrl) { + continue; + } + + const controller = new AbortController(); + + await scheduler.scheduleTask({ + id: `lighthouse_audit_${stringifyEntityRef(entity)}`, + frequency: {}, + timeout: {}, + initialDelay: { minutes: index * 2 }, + signal: controller.signal, + fn: async () => { + logger.info( + `Processing Website Url ${websiteUrl} for Entity ${entity.metadata.name}`, + ); + + await lighthouseApi.triggerAudit({ + url: websiteUrl, + options: { + lighthouseConfig: { + settings: { + formFactor: 'mobile', + emulatedFormFactor: 'mobile', + screenEmulation: formFactorToScreenEmulationMap.mobile, + }, + }, + }, + }); + + logger.info('Stop Scheduled Task'); + controller.abort(); + }, + }); + index++; + } + }, + }); + } +} diff --git a/plugins/lighthouse-backend/src/setupTests.ts b/plugins/lighthouse-backend/src/setupTests.ts new file mode 100644 index 0000000000..d3232290a7 --- /dev/null +++ b/plugins/lighthouse-backend/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/lighthouse-common/.eslintrc.js b/plugins/lighthouse-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/lighthouse-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/lighthouse-common/CHANGELOG.md b/plugins/lighthouse-common/CHANGELOG.md new file mode 100644 index 0000000000..189507371a --- /dev/null +++ b/plugins/lighthouse-common/CHANGELOG.md @@ -0,0 +1,12 @@ +# @backstage/plugin-lighthouse-common + +## 0.1.0-next.0 + +### Minor Changes + +- eef62546ce: Introduce @backstage/plugin-lighthouse-common with the API implementation + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 diff --git a/plugins/lighthouse-common/README.md b/plugins/lighthouse-common/README.md new file mode 100644 index 0000000000..9ab6d9a86d --- /dev/null +++ b/plugins/lighthouse-common/README.md @@ -0,0 +1,3 @@ +# @backstage/plugin-lighthouse-common + +Common types and functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend. diff --git a/plugins/lighthouse-common/api-report.md b/plugins/lighthouse-common/api-report.md new file mode 100644 index 0000000000..8589c20d2a --- /dev/null +++ b/plugins/lighthouse-common/api-report.md @@ -0,0 +1,161 @@ +## API Report File for "@backstage/plugin-lighthouse-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Config } from '@backstage/config'; + +// @public (undocumented) +export type Audit = AuditRunning | AuditFailed | AuditCompleted; + +// @public (undocumented) +export interface AuditBase { + // (undocumented) + id: string; + // (undocumented) + timeCreated: string; + // (undocumented) + url: string; +} + +// @public (undocumented) +export interface AuditCompleted extends AuditBase { + // (undocumented) + categories: Record; + // (undocumented) + report: Object; + // (undocumented) + status: 'COMPLETED'; + // (undocumented) + timeCompleted: string; +} + +// @public (undocumented) +export interface AuditFailed extends AuditBase { + // (undocumented) + status: 'FAILED'; + // (undocumented) + timeCompleted: string; +} + +// @public (undocumented) +export interface AuditRunning extends AuditBase { + // (undocumented) + status: 'RUNNING'; +} + +// @public (undocumented) +export class FetchError extends Error { + // (undocumented) + static forResponse(resp: Response): Promise; + // (undocumented) + get name(): string; +} + +// @public (undocumented) +export type FormFactor = 'mobile' | 'desktop'; + +// @public (undocumented) +export interface LASListRequest { + // (undocumented) + limit?: number; + // (undocumented) + offset?: number; +} + +// @public (undocumented) +export interface LASListResponse { + // (undocumented) + items: Item[]; + // (undocumented) + limit: number; + // (undocumented) + offset: number; + // (undocumented) + total: number; +} + +// @public (undocumented) +export type LighthouseApi = { + url: string; + getWebsiteList: (listOptions: LASListRequest) => Promise; + getWebsiteForAuditId: (auditId: string) => Promise; + triggerAudit: (payload: TriggerAuditPayload) => Promise; + getWebsiteByUrl: (websiteUrl: string) => Promise; +}; + +// @public (undocumented) +export interface LighthouseCategoryAbbr { + // (undocumented) + id: LighthouseCategoryId; + // (undocumented) + score: number; + // (undocumented) + title: string; +} + +// @public (undocumented) +export type LighthouseCategoryId = + | 'pwa' + | 'seo' + | 'performance' + | 'accessibility' + | 'best-practices'; + +// @public (undocumented) +export type LighthouseConfigSettings = { + formFactor: FormFactor; + screenEmulation: + | { + mobile: boolean; + width: number; + height: number; + deviceScaleFactor: number; + disabled: boolean; + } + | undefined; + emulatedFormFactor: FormFactor; +}; + +// @public (undocumented) +export class LighthouseRestApi implements LighthouseApi { + constructor(url: string); + // (undocumented) + static fromConfig(config: Config): LighthouseRestApi; + // (undocumented) + getWebsiteByUrl(websiteUrl: string): Promise; + // (undocumented) + getWebsiteForAuditId(auditId: string): Promise; + // (undocumented) + getWebsiteList(options?: LASListRequest): Promise; + // (undocumented) + triggerAudit(payload: TriggerAuditPayload): Promise; + // (undocumented) + url: string; +} + +// @public (undocumented) +export interface TriggerAuditPayload { + // (undocumented) + options: { + lighthouseConfig: { + settings: LighthouseConfigSettings; + }; + }; + // (undocumented) + url: string; +} + +// @public (undocumented) +export interface Website { + // (undocumented) + audits: Audit[]; + // (undocumented) + lastAudit: Audit; + // (undocumented) + url: string; +} + +// @public (undocumented) +export type WebsiteListResponse = LASListResponse; +``` diff --git a/plugins/lighthouse-common/package.json b/plugins/lighthouse-common/package.json new file mode 100644 index 0000000000..50281e17ba --- /dev/null +++ b/plugins/lighthouse-common/package.json @@ -0,0 +1,46 @@ +{ + "name": "@backstage/plugin-lighthouse-common", + "description": "Common functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend plugin", + "version": "0.1.0-next.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "common-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/lighthouse-common" + }, + "keywords": [ + "lighthouse" + ], + "files": [ + "dist" + ], + "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" + }, + "bugs": { + "url": "https://github.com/backstage/backstage/issues" + }, + "dependencies": { + "@backstage/config": "workspace:^" + }, + "devDependencies": { + "@backstage/cli": "workspace:^" + } +} diff --git a/plugins/lighthouse-common/src/api.ts b/plugins/lighthouse-common/src/api.ts new file mode 100644 index 0000000000..0abd6dacdc --- /dev/null +++ b/plugins/lighthouse-common/src/api.ts @@ -0,0 +1,188 @@ +/* + * 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 { Config } from '@backstage/config'; + +/** @public */ +export type LighthouseCategoryId = + | 'pwa' + | 'seo' + | 'performance' + | 'accessibility' + | 'best-practices'; + +/** @public */ +export interface LighthouseCategoryAbbr { + id: LighthouseCategoryId; + score: number; + title: string; +} + +/** @public */ +export interface LASListRequest { + offset?: number; + limit?: number; +} + +/** @public */ +export interface LASListResponse { + items: Item[]; + total: number; + offset: number; + limit: number; +} + +/** @public */ +export interface AuditBase { + id: string; + url: string; + timeCreated: string; +} + +/** @public */ +export interface AuditRunning extends AuditBase { + status: 'RUNNING'; +} + +/** @public */ +export interface AuditFailed extends AuditBase { + status: 'FAILED'; + timeCompleted: string; +} + +/** @public */ +export interface AuditCompleted extends AuditBase { + status: 'COMPLETED'; + timeCompleted: string; + report: Object; + categories: Record; +} + +/** @public */ +export type Audit = AuditRunning | AuditFailed | AuditCompleted; + +/** @public */ +export interface Website { + url: string; + audits: Audit[]; + lastAudit: Audit; +} + +/** @public */ +export type WebsiteListResponse = LASListResponse; + +/** @public */ +export type FormFactor = 'mobile' | 'desktop'; + +/** @public */ +export type LighthouseConfigSettings = { + // For lighthouse 7+ + formFactor: FormFactor; + screenEmulation: + | { + mobile: boolean; + width: number; + height: number; + deviceScaleFactor: number; + disabled: boolean; + } + | undefined; + // For lighthouse before 7 + emulatedFormFactor: FormFactor; +}; + +/** @public */ +export interface TriggerAuditPayload { + url: string; + options: { + lighthouseConfig: { + settings: LighthouseConfigSettings; + }; + }; +} + +/** @public */ +export class FetchError extends Error { + get name(): string { + return this.constructor.name; + } + + static async forResponse(resp: Response): Promise { + return new FetchError( + `Request failed with status code ${ + resp.status + }.\nReason: ${await resp.text()}`, + ); + } +} + +/** @public */ +export type LighthouseApi = { + url: string; + getWebsiteList: (listOptions: LASListRequest) => Promise; + getWebsiteForAuditId: (auditId: string) => Promise; + triggerAudit: (payload: TriggerAuditPayload) => Promise; + getWebsiteByUrl: (websiteUrl: string) => Promise; +}; + +/** @public */ +export class LighthouseRestApi implements LighthouseApi { + static fromConfig(config: Config) { + return new LighthouseRestApi(config.getString('lighthouse.baseUrl')); + } + + constructor(public url: string) {} + + private async fetch(input: string, init?: RequestInit): Promise { + const resp = await fetch(`${this.url}${input}`, init); + if (!resp.ok) throw await FetchError.forResponse(resp); + return await resp.json(); + } + + async getWebsiteList( + options: LASListRequest = {}, + ): Promise { + const { limit, offset } = options; + const params = new URLSearchParams(); + if (typeof limit === 'number') params.append('limit', limit.toString()); + if (typeof offset === 'number') params.append('offset', offset.toString()); + return await this.fetch( + `/v1/websites?${params.toString()}`, + ); + } + + async getWebsiteForAuditId(auditId: string): Promise { + return await this.fetch( + `/v1/audits/${encodeURIComponent(auditId)}/website`, + ); + } + + async triggerAudit(payload: TriggerAuditPayload): Promise { + return await this.fetch('/v1/audits', { + method: 'POST', + body: JSON.stringify(payload), + headers: { + 'Content-Type': 'application/json', + }, + }); + } + + async getWebsiteByUrl(websiteUrl: string): Promise { + return this.fetch( + `/v1/websites/${encodeURIComponent(websiteUrl)}`, + ); + } +} diff --git a/plugins/lighthouse-common/src/index.ts b/plugins/lighthouse-common/src/index.ts new file mode 100644 index 0000000000..41b839087f --- /dev/null +++ b/plugins/lighthouse-common/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. + */ + +/** + * Common functionalities for Lighthouse, to be shared between the `lighthouse` and `lighthouse-backend` plugins + * + * @packageDocumentation + */ + +export * from './api'; diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 8e21a89a8d..a79e4795e2 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-lighthouse +## 0.4.0-next.2 + +### Minor Changes + +- eef62546ce: Require @backstage/plugin-lighthouse-common package where API implementation moved to. + + **BREAKING**: the following types have been moved to @backstage/plugin-lighthouse-common: + + - `Audit` + - `AuditBase` + - `AuditCompleted` + - `AuditFailed` + - `AuditRunning` + - `FetchError` + - `LASListRequest` + - `LASListResponse` + - `LighthouseApi` + - `LighthouseCategoryAbbr` + - `LighthouseCategoryId` + - `LighthouseConfigSettings` + - `LighthouseRestApi` + - `TriggerAuditPayload` + - `Website` + - `WebsiteListResponse` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-lighthouse-common@0.1.0-next.0 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.3.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.15-next.0 ### Patch Changes diff --git a/plugins/lighthouse/README.md b/plugins/lighthouse/README.md index f07041d9ff..1d2385e4c4 100644 --- a/plugins/lighthouse/README.md +++ b/plugins/lighthouse/README.md @@ -105,3 +105,7 @@ const overviewContent = ( ``` + +## Schedule + +If you want to run automated scheduled runs, you can install the [@backstage/lighthouse-backend](../lighthouse-backend/README.md) plugin diff --git a/plugins/lighthouse/api-report.md b/plugins/lighthouse/api-report.md index e9089c7e92..4ab851472a 100644 --- a/plugins/lighthouse/api-report.md +++ b/plugins/lighthouse/api-report.md @@ -7,50 +7,11 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; -import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import { InfoCardVariants } from '@backstage/core-components'; +import { LighthouseApi } from '@backstage/plugin-lighthouse-common'; import { RouteRef } from '@backstage/core-plugin-api'; -// @public (undocumented) -export type Audit = AuditRunning | AuditFailed | AuditCompleted; - -// @public (undocumented) -export interface AuditBase { - // (undocumented) - id: string; - // (undocumented) - timeCreated: string; - // (undocumented) - url: string; -} - -// @public (undocumented) -export interface AuditCompleted extends AuditBase { - // (undocumented) - categories: Record; - // (undocumented) - report: Object; - // (undocumented) - status: 'COMPLETED'; - // (undocumented) - timeCompleted: string; -} - -// @public (undocumented) -export interface AuditFailed extends AuditBase { - // (undocumented) - status: 'FAILED'; - // (undocumented) - timeCompleted: string; -} - -// @public (undocumented) -export interface AuditRunning extends AuditBase { - // (undocumented) - status: 'RUNNING'; -} - // @public (undocumented) export const EmbeddedRouter: () => JSX.Element; @@ -63,93 +24,20 @@ export const EntityLastLighthouseAuditCard: (props: { // @public (undocumented) export const EntityLighthouseContent: () => JSX.Element; -// @public (undocumented) -export class FetchError extends Error { - // (undocumented) - static forResponse(resp: Response): Promise; - // (undocumented) - get name(): string; -} - -// @public (undocumented) -export type FormFactor = 'mobile' | 'desktop'; - // @public (undocumented) const isLighthouseAvailable: (entity: Entity) => boolean; export { isLighthouseAvailable }; export { isLighthouseAvailable as isPluginApplicableToEntity }; -// @public (undocumented) -export interface LASListRequest { - // (undocumented) - limit?: number; - // (undocumented) - offset?: number; -} - -// @public (undocumented) -export interface LASListResponse { - // (undocumented) - items: Item[]; - // (undocumented) - limit: number; - // (undocumented) - offset: number; - // (undocumented) - total: number; -} - // @public (undocumented) export const LastLighthouseAuditCard: (props: { dense?: boolean; variant?: InfoCardVariants; }) => JSX.Element; -// @public (undocumented) -export type LighthouseApi = { - url: string; - getWebsiteList: (listOptions: LASListRequest) => Promise; - getWebsiteForAuditId: (auditId: string) => Promise; - triggerAudit: (payload: TriggerAuditPayload) => Promise; - getWebsiteByUrl: (websiteUrl: string) => Promise; -}; - // @public (undocumented) export const lighthouseApiRef: ApiRef; -// @public (undocumented) -export interface LighthouseCategoryAbbr { - // (undocumented) - id: LighthouseCategoryId; - // (undocumented) - score: number; - // (undocumented) - title: string; -} - -// @public (undocumented) -export type LighthouseCategoryId = - | 'pwa' - | 'seo' - | 'performance' - | 'accessibility' - | 'best-practices'; - -// @public (undocumented) -export type LighthouseConfigSettings = { - formFactor: FormFactor; - screenEmulation: - | { - mobile: boolean; - width: number; - height: number; - deviceScaleFactor: number; - disabled: boolean; - } - | undefined; - emulatedFormFactor: FormFactor; -}; - // @public (undocumented) export const LighthousePage: () => JSX.Element; @@ -165,48 +53,6 @@ const lighthousePlugin: BackstagePlugin< export { lighthousePlugin }; export { lighthousePlugin as plugin }; -// @public (undocumented) -export class LighthouseRestApi implements LighthouseApi { - constructor(url: string); - // (undocumented) - static fromConfig(config: Config): LighthouseRestApi; - // (undocumented) - getWebsiteByUrl(websiteUrl: string): Promise; - // (undocumented) - getWebsiteForAuditId(auditId: string): Promise; - // (undocumented) - getWebsiteList(options?: LASListRequest): Promise; - // (undocumented) - triggerAudit(payload: TriggerAuditPayload): Promise; - // (undocumented) - url: string; -} - // @public (undocumented) export const Router: () => JSX.Element; - -// @public (undocumented) -export interface TriggerAuditPayload { - // (undocumented) - options: { - lighthouseConfig: { - settings: LighthouseConfigSettings; - }; - }; - // (undocumented) - url: string; -} - -// @public (undocumented) -export interface Website { - // (undocumented) - audits: Audit[]; - // (undocumented) - lastAudit: Audit; - // (undocumented) - url: string; -} - -// @public (undocumented) -export type WebsiteListResponse = LASListResponse; ``` diff --git a/plugins/lighthouse/dev/index.tsx b/plugins/lighthouse/dev/index.tsx index b5e7dd085e..41dd8761d9 100644 --- a/plugins/lighthouse/dev/index.tsx +++ b/plugins/lighthouse/dev/index.tsx @@ -16,7 +16,8 @@ import { createDevApp } from '@backstage/dev-utils'; import { lighthousePlugin } from '../src/plugin'; -import { lighthouseApiRef, LighthouseRestApi } from '../src'; +import { lighthouseApiRef } from '../src'; +import { LighthouseRestApi } from '@backstage/plugin-lighthouse-common'; createDevApp() .registerPlugin(lighthousePlugin) diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 242ca4b773..c52858b666 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.3.15-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/plugin-lighthouse-common": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", diff --git a/plugins/lighthouse/src/api.ts b/plugins/lighthouse/src/api.ts index a7197c4b96..8912f4838b 100644 --- a/plugins/lighthouse/src/api.ts +++ b/plugins/lighthouse/src/api.ts @@ -14,181 +14,10 @@ * limitations under the License. */ -import { Config } from '@backstage/config'; import { createApiRef } from '@backstage/core-plugin-api'; - -/** @public */ -export type LighthouseCategoryId = - | 'pwa' - | 'seo' - | 'performance' - | 'accessibility' - | 'best-practices'; - -/** @public */ -export interface LighthouseCategoryAbbr { - id: LighthouseCategoryId; - score: number; - title: string; -} - -/** @public */ -export interface LASListRequest { - offset?: number; - limit?: number; -} - -/** @public */ -export interface LASListResponse { - items: Item[]; - total: number; - offset: number; - limit: number; -} - -/** @public */ -export interface AuditBase { - id: string; - url: string; - timeCreated: string; -} - -/** @public */ -export interface AuditRunning extends AuditBase { - status: 'RUNNING'; -} - -/** @public */ -export interface AuditFailed extends AuditBase { - status: 'FAILED'; - timeCompleted: string; -} - -/** @public */ -export interface AuditCompleted extends AuditBase { - status: 'COMPLETED'; - timeCompleted: string; - report: Object; - categories: Record; -} - -/** @public */ -export type Audit = AuditRunning | AuditFailed | AuditCompleted; - -/** @public */ -export interface Website { - url: string; - audits: Audit[]; - lastAudit: Audit; -} - -/** @public */ -export type WebsiteListResponse = LASListResponse; - -/** @public */ -export type FormFactor = 'mobile' | 'desktop'; - -/** @public */ -export type LighthouseConfigSettings = { - // For lighthouse 7+ - formFactor: FormFactor; - screenEmulation: - | { - mobile: boolean; - width: number; - height: number; - deviceScaleFactor: number; - disabled: boolean; - } - | undefined; - // For lighthouse before 7 - emulatedFormFactor: FormFactor; -}; - -/** @public */ -export interface TriggerAuditPayload { - url: string; - options: { - lighthouseConfig: { - settings: LighthouseConfigSettings; - }; - }; -} - -/** @public */ -export class FetchError extends Error { - get name(): string { - return this.constructor.name; - } - - static async forResponse(resp: Response): Promise { - return new FetchError( - `Request failed with status code ${ - resp.status - }.\nReason: ${await resp.text()}`, - ); - } -} - -/** @public */ -export type LighthouseApi = { - url: string; - getWebsiteList: (listOptions: LASListRequest) => Promise; - getWebsiteForAuditId: (auditId: string) => Promise; - triggerAudit: (payload: TriggerAuditPayload) => Promise; - getWebsiteByUrl: (websiteUrl: string) => Promise; -}; +import { LighthouseApi } from '@backstage/plugin-lighthouse-common'; /** @public */ export const lighthouseApiRef = createApiRef({ id: 'plugin.lighthouse.service', }); - -/** @public */ -export class LighthouseRestApi implements LighthouseApi { - static fromConfig(config: Config) { - return new LighthouseRestApi(config.getString('lighthouse.baseUrl')); - } - - constructor(public url: string) {} - - private async fetch(input: string, init?: RequestInit): Promise { - const resp = await fetch(`${this.url}${input}`, init); - if (!resp.ok) throw await FetchError.forResponse(resp); - return await resp.json(); - } - - async getWebsiteList( - options: LASListRequest = {}, - ): Promise { - const { limit, offset } = options; - const params = new URLSearchParams(); - if (typeof limit === 'number') params.append('limit', limit.toString()); - if (typeof offset === 'number') params.append('offset', offset.toString()); - return await this.fetch( - `/v1/websites?${params.toString()}`, - ); - } - - async getWebsiteForAuditId(auditId: string): Promise { - return await this.fetch( - `/v1/audits/${encodeURIComponent(auditId)}/website`, - ); - } - - async triggerAudit(payload: TriggerAuditPayload): Promise { - return await this.fetch('/v1/audits', { - method: 'POST', - body: JSON.stringify(payload), - headers: { - 'Content-Type': 'application/json', - }, - }); - } - - async getWebsiteByUrl(websiteUrl: string): Promise { - return this.fetch( - `/v1/websites/${encodeURIComponent(websiteUrl)}`, - ); - } -} diff --git a/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx b/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx index 59892e1475..d1ed72c3fb 100644 --- a/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/AuditListForEntity.test.tsx @@ -19,10 +19,10 @@ import { EntityProvider } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { - lighthouseApiRef, LighthouseRestApi, WebsiteListResponse, -} from '../../api'; +} from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity'; import * as data from '../../__fixtures__/website-list-response.json'; import { AuditListForEntity } from './AuditListForEntity'; diff --git a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx index c2ee202841..45889a2cd3 100644 --- a/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/AuditListTable.test.tsx @@ -25,9 +25,9 @@ import AuditListTable from './AuditListTable'; import { WebsiteListResponse, - lighthouseApiRef, LighthouseRestApi, -} from '../../api'; +} from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import { formatTime } from '../../utils'; import { setupServer } from 'msw/node'; import * as data from '../../__fixtures__/website-list-response.json'; diff --git a/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx b/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx index 9f5fa94436..8f718cda64 100644 --- a/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx +++ b/plugins/lighthouse/src/components/AuditList/AuditListTable.tsx @@ -15,7 +15,8 @@ */ import React, { useState, useEffect } from 'react'; import Typography from '@material-ui/core/Typography'; -import { Website, lighthouseApiRef } from '../../api'; +import { Website } from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import useInterval from 'react-use/lib/useInterval'; import { formatTime, diff --git a/plugins/lighthouse/src/components/AuditList/index.test.tsx b/plugins/lighthouse/src/components/AuditList/index.test.tsx index 2b422cce7a..55bde9aebd 100644 --- a/plugins/lighthouse/src/components/AuditList/index.test.tsx +++ b/plugins/lighthouse/src/components/AuditList/index.test.tsx @@ -33,10 +33,10 @@ import { rest } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; import { - lighthouseApiRef, LighthouseRestApi, WebsiteListResponse, -} from '../../api'; +} from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import * as data from '../../__fixtures__/website-list-response.json'; import AuditList from './index'; import { ApiProvider } from '@backstage/core-app-api'; diff --git a/plugins/lighthouse/src/components/AuditStatusIcon/index.tsx b/plugins/lighthouse/src/components/AuditStatusIcon/index.tsx index 52ba2e00cf..b0e1c876ae 100644 --- a/plugins/lighthouse/src/components/AuditStatusIcon/index.tsx +++ b/plugins/lighthouse/src/components/AuditStatusIcon/index.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Audit } from '../../api'; +import { Audit } from '@backstage/plugin-lighthouse-common'; import { StatusError, StatusOK, diff --git a/plugins/lighthouse/src/components/AuditView/index.test.tsx b/plugins/lighthouse/src/components/AuditView/index.test.tsx index d555133f3e..7e7d8e4b7d 100644 --- a/plugins/lighthouse/src/components/AuditView/index.test.tsx +++ b/plugins/lighthouse/src/components/AuditView/index.test.tsx @@ -38,7 +38,12 @@ import { render } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; -import { Audit, lighthouseApiRef, LighthouseRestApi, Website } from '../../api'; +import { + Audit, + LighthouseRestApi, + Website, +} from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import { formatTime } from '../../utils'; import * as data from '../../__fixtures__/website-response.json'; import AuditView from './index'; diff --git a/plugins/lighthouse/src/components/AuditView/index.tsx b/plugins/lighthouse/src/components/AuditView/index.tsx index ade485b09a..8d82f920cd 100644 --- a/plugins/lighthouse/src/components/AuditView/index.tsx +++ b/plugins/lighthouse/src/components/AuditView/index.tsx @@ -33,7 +33,8 @@ import { useParams, } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; -import { Audit, lighthouseApiRef, Website } from '../../api'; +import { Audit, Website } from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import { formatTime } from '../../utils'; import AuditStatusIcon from '../AuditStatusIcon'; import LighthouseSupportButton from '../SupportButton'; diff --git a/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.test.tsx b/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.test.tsx index c59458f3f3..09b21fd028 100644 --- a/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.test.tsx +++ b/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.test.tsx @@ -22,7 +22,7 @@ import { AuditCompleted, LighthouseCategoryId, WebsiteListResponse, -} from '../../api'; +} from '@backstage/plugin-lighthouse-common'; import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity'; import * as data from '../../__fixtures__/website-list-response.json'; import { LastLighthouseAuditCard } from './LastLighthouseAuditCard'; diff --git a/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.tsx b/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.tsx index 1562031007..af5ce94487 100644 --- a/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.tsx +++ b/plugins/lighthouse/src/components/Cards/LastLighthouseAuditCard.tsx @@ -15,7 +15,11 @@ */ import React from 'react'; import Typography from '@material-ui/core/Typography'; -import { Audit, AuditCompleted, LighthouseCategoryId } from '../../api'; +import { + Audit, + AuditCompleted, + LighthouseCategoryId, +} from '@backstage/plugin-lighthouse-common'; import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity'; import AuditStatusIcon from '../AuditStatusIcon'; import { diff --git a/plugins/lighthouse/src/components/CreateAudit/index.test.tsx b/plugins/lighthouse/src/components/CreateAudit/index.test.tsx index 60a7bc1301..1b394a30f0 100644 --- a/plugins/lighthouse/src/components/CreateAudit/index.test.tsx +++ b/plugins/lighthouse/src/components/CreateAudit/index.test.tsx @@ -32,7 +32,8 @@ import { fireEvent, render, waitFor } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import React from 'react'; -import { Audit, lighthouseApiRef, LighthouseRestApi } from '../../api'; +import { Audit, LighthouseRestApi } from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import * as data from '../../__fixtures__/create-audit-response.json'; import CreateAudit from './index'; diff --git a/plugins/lighthouse/src/components/CreateAudit/index.tsx b/plugins/lighthouse/src/components/CreateAudit/index.tsx index 8ed7dc8996..a76b031796 100644 --- a/plugins/lighthouse/src/components/CreateAudit/index.tsx +++ b/plugins/lighthouse/src/components/CreateAudit/index.tsx @@ -27,9 +27,9 @@ import React, { useCallback, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { FormFactor, - lighthouseApiRef, LighthouseConfigSettings, -} from '../../api'; +} from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../../api'; import { useQuery } from '../../utils'; import LighthouseSupportButton from '../SupportButton'; diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 13da0f6f4f..7ab717c57d 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -17,7 +17,8 @@ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import { renderHook } from '@testing-library/react-hooks'; import React, { PropsWithChildren } from 'react'; -import { lighthouseApiRef, WebsiteListResponse } from '../api'; +import { WebsiteListResponse } from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from '../api'; import * as data from '../__fixtures__/website-list-response.json'; import { useWebsiteForEntity } from './useWebsiteForEntity'; diff --git a/plugins/lighthouse/src/plugin.ts b/plugins/lighthouse/src/plugin.ts index 24052f7771..3458ae7240 100644 --- a/plugins/lighthouse/src/plugin.ts +++ b/plugins/lighthouse/src/plugin.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { lighthouseApiRef, LighthouseRestApi } from './api'; +import { LighthouseRestApi } from '@backstage/plugin-lighthouse-common'; +import { lighthouseApiRef } from './api'; import { createPlugin, createRouteRef, diff --git a/plugins/lighthouse/src/utils.ts b/plugins/lighthouse/src/utils.ts index b255f2f90e..918995386d 100644 --- a/plugins/lighthouse/src/utils.ts +++ b/plugins/lighthouse/src/utils.ts @@ -14,7 +14,12 @@ * limitations under the License. */ import { useLocation } from 'react-router-dom'; -import { Website, Audit, LighthouseCategoryId, AuditCompleted } from './api'; +import { + Website, + Audit, + LighthouseCategoryId, + AuditCompleted, +} from '@backstage/plugin-lighthouse-common'; export function useQuery(): URLSearchParams { return new URLSearchParams(useLocation().search); diff --git a/plugins/microsoft-calendar/.eslintrc.js b/plugins/microsoft-calendar/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/microsoft-calendar/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/microsoft-calendar/README.md b/plugins/microsoft-calendar/README.md new file mode 100644 index 0000000000..73a66b15f5 --- /dev/null +++ b/plugins/microsoft-calendar/README.md @@ -0,0 +1,51 @@ +# Microsoft-Calendar Plugin + +Welcome to the Microsoft calendar plugin! +_This plugin was created through the Backstage CLI_ + +## Features + +1. You can switch between calendars, using the select menu on the calendar card header. +2. Card showing the list of events on the selected date and the selected calendar (provided by Outlook calendar). +3. Link to join the online meeting on the event card if provided. so you can join your meetings right away hassle-free. +4. Hovering over the event will pop over a card showing the event summary message, and list of attendees. +5. attendee's chips will have a badge over them symbolizing their responses. + - green --> accepted + - red --> declined + - nothing --> not responded yet + +## Setup + +The following sections will help you set up the Microsoft calendar plugin. + +### Microsoft azure authentication provider + +> You need to setup [Microsoft Azure authentication provider](https://backstage.io/docs/auth/microsoft/provider), before you move forward with any of the below step if you haven't already. + +1. Install the plugin by running this command + +```bash +# From the Backstage repository root +yarn add --cwd packages/app @backstage/plugin-microsoft-calendar +``` + +2. Import the Microsoft calendar React component from `@backstage/plugin-microsoft-calendar`. +3. You can then use the provided React component `MicrosoftCalendar` in the backstage frontend where ever you want + +```tsx +import { MicrosoftCalendar } from '@backstage/plugin-microsoft-calendar'; + +// ... + + +; +// ... +``` + +![Microsoft Calendar plugin demo](https://user-images.githubusercontent.com/23618736/215717491-25db5fa6-b237-487f-8c00-28f572e8da05.mp4) + +![Sample](./docs/microsoft-calendar-plugin.png) + +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, and the setup for it can be found inside the [/dev](./dev) directory. diff --git a/plugins/microsoft-calendar/api-report.md b/plugins/microsoft-calendar/api-report.md new file mode 100644 index 0000000000..d6839f19ea --- /dev/null +++ b/plugins/microsoft-calendar/api-report.md @@ -0,0 +1,39 @@ +## API Report File for "@backstage/plugin-microsoft-calendar" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiRef } from '@backstage/core-plugin-api'; +import { Calendar } from '@microsoft/microsoft-graph-types'; +import { Event as Event_2 } from '@microsoft/microsoft-graph-types'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { OAuthApi } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export class MicrosoftCalendarApiClient { + constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }); + // (undocumented) + getCalendars(): Promise; + // (undocumented) + getEvents( + calendarId: string, + params: { + startDateTime: string; + endDateTime: string; + }, + headers: { + [key in string]: any; + }, + ): Promise; +} + +// @public (undocumented) +export const microsoftCalendarApiRef: ApiRef; + +// @public (undocumented) +export const MicrosoftCalendarCard: () => JSX.Element; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/microsoft-calendar/dev/index.tsx b/plugins/microsoft-calendar/dev/index.tsx new file mode 100644 index 0000000000..d611bca20c --- /dev/null +++ b/plugins/microsoft-calendar/dev/index.tsx @@ -0,0 +1,63 @@ +/* + * Copyright 2023 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 { createDevApp } from '@backstage/dev-utils'; +import { microsoftCalendarPlugin, MicrosoftCalendarCard } from '../src/plugin'; +import { microsoftCalendarApiRef } from '../src'; +import responseMock from './mock.json'; +import { microsoftAuthApiRef } from '@backstage/core-plugin-api'; +import { Content, Page } from '@backstage/core-components'; +import { Grid } from '@material-ui/core'; + +createDevApp() + .registerPlugin(microsoftCalendarPlugin) + .registerApi({ + api: microsoftAuthApiRef, + deps: {}, + factory: () => + ({ + async getAccessToken() { + return Promise.resolve('token'); + }, + } as unknown as typeof microsoftAuthApiRef.T), + }) + .registerApi({ + api: microsoftCalendarApiRef, + deps: {}, + factory: () => + ({ + async getCalendars() { + return Promise.resolve(responseMock.calendars); + }, + async getEvents() { + return Promise.resolve(responseMock.events); + }, + } as unknown as typeof microsoftCalendarApiRef.T), + }) + .addPage({ + element: ( + + + + + + + + ), + title: 'Microsoft-Calendar Plugin Demo', + path: '/microsoft-calendar', + }) + .render(); diff --git a/plugins/microsoft-calendar/dev/mock.json b/plugins/microsoft-calendar/dev/mock.json new file mode 100644 index 0000000000..b305e187eb --- /dev/null +++ b/plugins/microsoft-calendar/dev/mock.json @@ -0,0 +1,305 @@ +{ + "calendars": [ + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIyswAAAA==", + "name": "Calendar", + "color": "lightBlue", + "hexColor": "#9fe1e7", + "isDefaultCalendar": true, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADYw==", + "canShare": true, + "canViewPrivateItems": true, + "canEdit": true, + "allowedOnlineMeetingProviders": ["teamsForBusiness"], + "defaultOnlineMeetingProvider": "teamsForBusiness", + "isTallyingResponses": true, + "isRemovable": false, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAEGAACkUjuDFCV2Q4tYcM6WC3rQAAAZs65BAAA=", + "name": "United Kingdom holidays", + "color": "auto", + "hexColor": "", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAGanqjg==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAEGAACkUjuDFCV2Q4tYcM6WC3rQAAAZs65CAAA=", + "name": "Birthdays1", + "color": "auto", + "hexColor": "", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAGanrfQ==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIytQAAAA==", + "name": "Birthdays", + "color": "auto", + "hexColor": "#92e1c0", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADdw==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + { + "id": "AQMkADQyMDdlODU1AC05OGNiLTRhZmItOGM2Mi1kODZhMzJkYWU2OTAARgAAAwWXy9axQ31DtBuHDIFwgtYHAKRSO4MUJXZDi1hwzpYLetAAAAIBBgAAAKRSO4MUJXZDi1hwzpYLetAAAAIytgAAAA==", + "name": "Holidays in India", + "color": "auto", + "hexColor": "#16a765", + "isDefaultCalendar": false, + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAAAADug==", + "canShare": false, + "canViewPrivateItems": true, + "canEdit": false, + "allowedOnlineMeetingProviders": [], + "defaultOnlineMeetingProvider": "unknown", + "isTallyingResponses": false, + "isRemovable": true, + "owner": { + "name": "Abhay Soni", + "address": "abhay.s@statusneo.com" + } + } + ], + "events": [ + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "Abhay Soni", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [ + { + "type": "required", + "status": { + "response": "none", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Nishkarsh Raj", + "address": "nishkarshraj@nishkarsh.com" + } + }, + { + "type": "required", + "status": { + "response": "accepted", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Hakam Ram", + "address": "hakam_ram@ram.com" + } + }, + { + "type": "required", + "status": { + "response": "declined", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + } + ], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "https://abhay-soni-developer.github.io/MyReusme/", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "attendees": [ + { + "type": "required", + "status": { + "response": "none", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Nishkarsh Raj", + "address": "nishkarshraj@nishkarsh.com" + } + }, + { + "type": "required", + "status": { + "response": "accepted", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Hakam Ram", + "address": "hakam_ram@ram.com" + } + }, + { + "type": "required", + "status": { + "response": "declined", + "time": "0001-01-01T00:00:00Z" + }, + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + } + ], + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + } + ] +} diff --git a/plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png b/plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png new file mode 100644 index 0000000000..376ae73717 Binary files /dev/null and b/plugins/microsoft-calendar/docs/microsoft-calendar-plugin.png differ diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json new file mode 100644 index 0000000000..2a2e0ca013 --- /dev/null +++ b/plugins/microsoft-calendar/package.json @@ -0,0 +1,63 @@ +{ + "name": "@backstage/plugin-microsoft-calendar", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "author": { + "name": "Abhay Soni", + "email": "abhaysoni.developer@gmail.com", + "url": "https://github.com/Abhay-soni-developer" + }, + "scripts": { + "start": "backstage-cli package start", + "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" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@microsoft/microsoft-graph-types": "^2.25.0", + "@tanstack/react-query": "^4.1.3", + "classnames": "^2.3.1", + "dompurify": "^2.3.6", + "lodash": "^4.17.21", + "luxon": "^3.0.0", + "material-ui-popup-state": "^1.9.3", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/user-event": "^14.0.0", + "@types/node": "^16.11.26", + "cross-fetch": "^3.1.5", + "msw": "^0.49.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/microsoft-calendar/src/api/client.ts b/plugins/microsoft-calendar/src/api/client.ts new file mode 100644 index 0000000000..fe842b5aef --- /dev/null +++ b/plugins/microsoft-calendar/src/api/client.ts @@ -0,0 +1,95 @@ +/* + * 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 { OAuthApi, createApiRef, FetchApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { MicrosoftCalendarEvent, MicrosoftCalendar } from './types'; + +/** @public */ +export const microsoftCalendarApiRef = createApiRef( + { + id: 'plugin.microsoft-calendar.service', + }, +); + +/** @public */ +export class MicrosoftCalendarApiClient { + private readonly authApi: OAuthApi; + private readonly fetchApi: FetchApi; + + constructor(options: { authApi: OAuthApi; fetchApi: FetchApi }) { + this.authApi = options.authApi; + this.fetchApi = options.fetchApi; + } + + private async get( + path: string, + params: { [key in string]: any } = {}, + headers?: any, + ): Promise { + const query = new URLSearchParams(params); + const url = new URL( + `${path}?${query.toString()}`, + 'https://graph.microsoft.com', + ); + const token = await this.authApi.getAccessToken(); + let temp: any = {}; + + if (headers && typeof headers === 'object') { + temp = { + ...headers, + }; + } + + if (token) { + temp.Authorization = `Bearer ${token}`; + } + + const response = await this.fetchApi.fetch(url.toString(), { + headers: temp, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } + + public async getCalendars(): Promise { + const data = await this.get<{ + id: string; + value: MicrosoftCalendar[]; + }>('v1.0/me/calendars'); + + return data.value; + } + + public async getEvents( + calendarId: string, + params: { + startDateTime: string; + endDateTime: string; + }, + headers: { [key in string]: any }, + ): Promise { + const data = await this.get<{ + id: string; + value: [MicrosoftCalendarEvent]; + }>(`v1.0/me/calendars/${calendarId}/calendarview`, params, headers); + return data.value; + } +} diff --git a/plugins/microsoft-calendar/src/api/index.ts b/plugins/microsoft-calendar/src/api/index.ts new file mode 100644 index 0000000000..db4616b586 --- /dev/null +++ b/plugins/microsoft-calendar/src/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 './client'; +export * from './types'; diff --git a/plugins/microsoft-calendar/src/api/types.ts b/plugins/microsoft-calendar/src/api/types.ts new file mode 100644 index 0000000000..f4cb2811c7 --- /dev/null +++ b/plugins/microsoft-calendar/src/api/types.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { + Calendar as MicrosoftCalendar, + Event as MicrosoftCalendarEvent, + Attendee, + ResponseStatus, + DateTimeTimeZone, + EmailAddress, +} from '@microsoft/microsoft-graph-types'; + +export type { + MicrosoftCalendar, + MicrosoftCalendarEvent, + Attendee, + ResponseStatus, + DateTimeTimeZone, + EmailAddress, +}; + +export const ResponseStatusMap = { + needsAction: 'none', + accepted: 'accepted', + declined: 'declined', + maybe: 'tentativelyAccepted', + notResponded: 'notResponded', +}; diff --git a/plugins/microsoft-calendar/src/components/AttendeeChip.tsx b/plugins/microsoft-calendar/src/components/AttendeeChip.tsx new file mode 100644 index 0000000000..67dd601da7 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/AttendeeChip.tsx @@ -0,0 +1,89 @@ +/* + * 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 { BackstageTheme } from '@backstage/theme'; + +import { Badge, Chip, makeStyles } from '@material-ui/core'; +import CancelIcon from '@material-ui/icons/Cancel'; +import CheckIcon from '@material-ui/icons/CheckCircle'; + +import { Attendee, ResponseStatusMap } from '../api'; + +const useStyles = makeStyles((theme: BackstageTheme) => { + const getIconColor = (responseStatus?: string) => { + if (!responseStatus) return theme.palette.primary.light; + + return { + [ResponseStatusMap.accepted]: theme.palette.status.ok, + [ResponseStatusMap.declined]: theme.palette.status.error, + }[responseStatus]; + }; + + return { + responseStatus: { + color: ({ responseStatus }: { responseStatus?: string }) => + getIconColor(responseStatus), + }, + badge: { + right: 10, + top: 5, + '& svg': { + height: 16, + width: 16, + background: '#fff', + }, + }, + }; +}); + +const ResponseIcon = ({ responseStatus }: { responseStatus: string }) => { + if (responseStatus === ResponseStatusMap.accepted) { + return ; + } + if (responseStatus === ResponseStatusMap.declined) { + return ; + } + + return null; +}; + +type AttendeeChipProps = { + user: Attendee; +}; + +export const AttendeeChip = ({ user }: AttendeeChipProps) => { + const classes = useStyles({ responseStatus: user.status?.response || '' }); + + return ( + + } + > + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarCard.tsx b/plugins/microsoft-calendar/src/components/CalendarCard.tsx new file mode 100644 index 0000000000..dd94bad148 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarCard.tsx @@ -0,0 +1,141 @@ +/* + * 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 { sortBy } from 'lodash'; +import { DateTime } from 'luxon'; +import React, { useState } from 'react'; + +import { InfoCard, Progress } from '@backstage/core-components'; + +import { Box, IconButton, Typography } from '@material-ui/core'; +import PrevIcon from '@material-ui/icons/NavigateBefore'; +import NextIcon from '@material-ui/icons/NavigateNext'; + +import { useCalendarsQuery, useEventsQuery, useSignIn } from '../hooks'; +import calendarIcon from '../icons/calendar.svg'; +import { CalendarEvent } from './CalendarEvent'; +import { CalendarSelect } from './CalendarSelect'; +import { SignInContent } from './SignInContent'; +import { getStartDate } from './util'; +import useAsync from 'react-use/lib/useAsync'; + +export const CalendarCard = () => { + const [date, setDate] = useState(DateTime.now()); + const [selectedCalendarId, setSelectedCalendarId] = useState(''); + + const changeDay = (offset = 1) => { + setDate(prev => prev.plus({ day: offset })); + }; + + const { isSignedIn, isInitialized, signIn } = useSignIn(); + + useAsync(async () => signIn(true), [signIn]); + + const { + isLoading: isCalendarLoading, + isFetching: isCalendarFetching, + data: calendars = [], + } = useCalendarsQuery({ + enabled: isSignedIn, + }); + + const defaultCalendarId = calendars.find(c => c.isDefaultCalendar)?.id; + + const { data: events, isLoading: isEventLoading } = useEventsQuery({ + calendarId: selectedCalendarId || defaultCalendarId || '', + enabled: isSignedIn && calendars.length > 0, + timeMin: date.startOf('day').toISO(), + timeMax: date.endOf('day').toISO(), + timeZone: date.zoneName, + }); + + const showLoader = + (isCalendarLoading && isCalendarFetching) || + isEventLoading || + !isInitialized; + + return ( + + + Microsoft Calendar + + {isSignedIn ? ( + <> + changeDay(-1)} size="small"> + + + changeDay(1)} size="small"> + + + + + {date.toLocaleString({ + weekday: 'short', + month: 'short', + day: 'numeric', + })} + + + + + + + ) : ( + Agenda + )} + + } + deepLink={{ + link: 'https://outlook.office.com/calendar/', + title: 'Go to Calendar', + }} + > + + {showLoader && ( + + + + )} + {!isSignedIn && isInitialized && ( + signIn(false)} /> + )} + {!isEventLoading && !isCalendarLoading && isSignedIn && ( + + {events?.length === 0 && ( + + + No events + + + )} + {sortBy(events, [getStartDate]).map(event => ( + + ))} + + )} + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarEvent.tsx b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx new file mode 100644 index 0000000000..e56e25a09b --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarEvent.tsx @@ -0,0 +1,166 @@ +/* + * 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 classnames from 'classnames'; +import { + bindPopover, + bindTrigger, + usePopupState, +} from 'material-ui-popup-state/hooks'; +import React, { useState } from 'react'; + +import { Link } from '@backstage/core-components'; + +import { + Box, + Paper, + Popover, + Tooltip, + Typography, + makeStyles, +} from '@material-ui/core'; + +import webcamIcon from '../icons/webcam.svg'; +import { CalendarEventPopoverContent } from './CalendarEventPopoverContent'; +import { MicrosoftCalendarEvent } from '../api'; +import { + getOnlineMeetingLink, + getTimePeriod, + isAllDay, + isPassed, +} from './util'; + +const useStyles = makeStyles( + theme => ({ + event: { + display: 'flex', + alignItems: 'center', + marginBottom: theme.spacing(1), + cursor: 'pointer', + paddingRight: 12, + }, + declined: { + textDecoration: 'line-through', + }, + passed: { + opacity: 0.6, + transition: 'opacity 0.15s ease-in-out', + '&:hover': { + opacity: 1, + }, + }, + link: { + width: 48, + height: 48, + display: 'inline-block', + padding: 8, + borderRadius: '50%', + '&:hover': { + backgroundColor: theme.palette.grey[100], + }, + }, + calendarColor: { + width: 8, + borderTopLeftRadius: 4, + borderBottomLeftRadius: 4, + }, + }), + { + name: 'MicrosoftCalendarEvent', + }, +); + +export const CalendarEvent = ({ event }: { event: MicrosoftCalendarEvent }) => { + const classes = useStyles(); + const popoverState = usePopupState({ + variant: 'popover', + popupId: event.id, + disableAutoFocus: true, + }); + const [hovered, setHovered] = useState(false); + const onlineMeetingLink = getOnlineMeetingLink(event); + + const { onClick, ...restBindProps } = bindTrigger(popoverState); + + return ( + <> + { + onClick(e); + }} + {...restBindProps} + onMouseEnter={() => setHovered(true)} + onMouseLeave={() => setHovered(false)} + elevation={hovered ? 4 : 1} + className={classnames(classes.event, { + [classes.passed]: isPassed(event), + })} + data-testid="microsoft-calendar-event" + > + + + + {event.subject} + + {!isAllDay(event) && ( + + {getTimePeriod(event)} + + )} + + + {event.isOnlineMeeting && ( + + { + e.stopPropagation(); + }} + noTrack + > + {/* we can use onlineMeetingProvider to show icon accordingly */} + Online Meeting link + + + )} + + + + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx new file mode 100644 index 0000000000..715a1ad276 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarEventPopoverContent.tsx @@ -0,0 +1,126 @@ +/* + * 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 { sortBy } from 'lodash'; +import React from 'react'; +import DOMPurify from 'dompurify'; + +import { Link } from '@backstage/core-components'; +import { + Box, + Divider, + IconButton, + Tooltip, + Typography, + makeStyles, +} from '@material-ui/core'; +import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; + +import { AttendeeChip } from './AttendeeChip'; +import { MicrosoftCalendarEvent } from '../api'; +import { getTimePeriod, getOnlineMeetingLink } from './util'; + +const useStyles = makeStyles( + theme => ({ + description: { + wordBreak: 'break-word', + '& a': { + color: theme.palette.primary.main, + fontWeight: 500, + }, + }, + divider: { + marginTop: theme.spacing(2), + marginBottom: theme.spacing(2), + }, + }), + { + name: 'MicrosoftCalendarEventPopoverContent', + }, +); + +type CalendarEventPopoverProps = { + event: MicrosoftCalendarEvent; +}; + +export const CalendarEventPopoverContent = ({ + event, +}: CalendarEventPopoverProps) => { + const classes = useStyles(); + const onlineMeetingLink = getOnlineMeetingLink(event); + + return ( + + + + {event.subject} + {getTimePeriod(event)} + + {event.webLink && ( + + {}} + noTrack + > + + + + + + )} + + {onlineMeetingLink && ( + {}} noTrack> + Join Online Meeting + + )} + + {event.bodyPreview && ( + <> + + + + )} + + {event.attendees && ( + <> + + + Attendees + + {sortBy(event.attendees || [], 'emailAddress').map(user => ( + + ))} + + + )} + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/CalendarSelect.tsx b/plugins/microsoft-calendar/src/components/CalendarSelect.tsx new file mode 100644 index 0000000000..59e2376079 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/CalendarSelect.tsx @@ -0,0 +1,92 @@ +/* + * 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 { sortBy } from 'lodash'; +import React from 'react'; + +import { + Checkbox, + FormControl, + Input, + ListItemText, + MenuItem, + Select, + Typography, + makeStyles, +} from '@material-ui/core'; +import { MicrosoftCalendar } from '../api'; + +const useStyles = makeStyles( + { + formControl: { + width: 120, + }, + selectedCalendars: { + textOverflow: 'ellipsis', + overflow: 'hidden', + }, + }, + { + name: 'MicrosoftCalendarSelect', + }, +); + +type CalendarSelectProps = { + disabled: boolean; + selectedCalendarId?: string; + setSelectedCalendarId: (value: string) => void; + calendars: MicrosoftCalendar[]; +}; + +export const CalendarSelect = ({ + disabled, + selectedCalendarId, + setSelectedCalendarId, + calendars, +}: CalendarSelectProps) => { + const classes = useStyles(); + return ( + + } + renderValue={selected => { + return ( + + {calendars.find(c => c.id === selected)?.name} + + ); + }} + MenuProps={{ + PaperProps: { + style: { + width: 350, + }, + }, + }} + > + {sortBy(calendars, 'name').map(c => ( + + + + + ))} + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx b/plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx new file mode 100644 index 0000000000..3bb15f7762 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/MicrosoftCalendar.tsx @@ -0,0 +1,29 @@ +/* + * 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 { QueryClient, QueryClientProvider } from '@tanstack/react-query'; + +import { CalendarCard } from './CalendarCard'; + +const queryClient = new QueryClient(); + +export const MicrosoftCalendar = () => { + return ( + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/SignInContent.tsx b/plugins/microsoft-calendar/src/components/SignInContent.tsx new file mode 100644 index 0000000000..d33698f68c --- /dev/null +++ b/plugins/microsoft-calendar/src/components/SignInContent.tsx @@ -0,0 +1,62 @@ +/* + * 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 { Box, Button, styled } from '@material-ui/core'; +import { CalendarEvent } from './CalendarEvent'; +import mockEvents from './eventMock.json'; +import { MicrosoftCalendarEvent } from '../api'; + +type Props = { + handleAuthClick: React.MouseEventHandler; +}; + +const TransparentBox = styled(Box)({ + opacity: 0.3, + filter: 'blur(1.5px)', +}); + +export const SignInContent = ({ handleAuthClick }: Props) => { + return ( + + + {(mockEvents as MicrosoftCalendarEvent[]).map(event => ( + + ))} + + + + + + + ); +}; diff --git a/plugins/microsoft-calendar/src/components/eventMock.json b/plugins/microsoft-calendar/src/components/eventMock.json new file mode 100644 index 0000000000..b648d1b486 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/eventMock.json @@ -0,0 +1,138 @@ +[ + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "Abhay Soni", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + }, + { + "id": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MAFRAAgI2vdUnGxAAEYAAAAABZfL1rFDfUO0G4cMgXCC1gcApFI7gxQldkOLWHDOlgt60AAAAAABDQAApFI7gxQldkOLWHDOlgt60AAAYl_I0AAAEA==", + "createdDateTime": "2022-12-22T08:28:36.6131501Z", + "lastModifiedDateTime": "2023-01-20T05:24:31.9666518Z", + "changeKey": "pFI7gxQldkOLWHDOlgt60AAAd5KhaA==", + "categories": [], + "transactionId": null, + "originalStartTimeZone": "India Standard Time", + "originalEndTimeZone": "India Standard Time", + "iCalUId": "040000008200E00074C5B7101A82E00807E7011006D3A5A92DC7D80100000000000000001000000002BB709705E28C4493E46124FF07DD89", + "reminderMinutesBeforeStart": 15, + "isReminderOn": true, + "hasAttachments": false, + "subject": "https://abhay-soni-developer.github.io/MyReusme/", + "bodyPreview": "", + "importance": "normal", + "sensitivity": "normal", + "isAllDay": false, + "isCancelled": false, + "isOrganizer": false, + "responseRequested": true, + "seriesMasterId": "AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=", + "showAs": "tentative", + "type": "occurrence", + "webLink": "", + "onlineMeetingUrl": "", + "isOnlineMeeting": true, + "onlineMeetingProvider": "teamsForBusiness", + "allowNewTimeProposals": true, + "occurrenceId": "OID.AAMkADQyMDdlODU1LTk4Y2ItNGFmYi04YzYyLWQ4NmEzMmRhZTY5MABGAAAAAAAFl8vWsUN9Q7QbhwyBcILWBwCkUjuDFCV2Q4tYcM6WC3rQAAAAAAENAACkUjuDFCV2Q4tYcM6WC3rQAABiX4jQAAA=.2023-01-16", + "isDraft": false, + "hideAttendees": false, + "responseStatus": { + "response": "notResponded", + "time": "0001-01-01T00:00:00Z" + }, + "body": { + "contentType": "html", + "content": "" + }, + "start": { + "dateTime": "2023-01-16T11:00:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "end": { + "dateTime": "2023-01-16T11:30:00.0000000", + "timeZone": "Asia/Calcutta" + }, + "location": { + "displayName": "", + "locationType": "default", + "uniqueIdType": "unknown", + "address": {}, + "coordinates": {} + }, + "locations": [], + "recurrence": null, + "attendees": [], + "organizer": { + "emailAddress": { + "name": "Abhay Soni", + "address": "abhaysoni.developer@gmail.com" + } + }, + "onlineMeeting": { + "joinUrl": "https://abhay-soni-developer.github.io/MyReusme/" + } + } +] diff --git a/plugins/microsoft-calendar/src/components/index.ts b/plugins/microsoft-calendar/src/components/index.ts new file mode 100644 index 0000000000..8149695804 --- /dev/null +++ b/plugins/microsoft-calendar/src/components/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { MicrosoftCalendar } from './MicrosoftCalendar'; diff --git a/plugins/microsoft-calendar/src/components/util.ts b/plugins/microsoft-calendar/src/components/util.ts new file mode 100644 index 0000000000..dd52402d9d --- /dev/null +++ b/plugins/microsoft-calendar/src/components/util.ts @@ -0,0 +1,76 @@ +/* + * 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 { DateTime } from 'luxon'; + +import { MicrosoftCalendarEvent } from '../api'; + +export function getOnlineMeetingLink(event: MicrosoftCalendarEvent) { + const onlineEntrypoint = + event.onlineMeeting?.joinUrl || event.onlineMeetingUrl; + if (onlineEntrypoint) { + return onlineEntrypoint; + } + return ''; +} + +export function getTimePeriod(event: MicrosoftCalendarEvent) { + if (isAllDay(event)) { + return getAllDayTimePeriod(event); + } + + const format: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + }; + + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || ''); + + return `${startTime.toLocaleString(format)} - ${endTime.toLocaleString( + format, + )}`; +} + +function getAllDayTimePeriod(event: MicrosoftCalendarEvent) { + const format: Intl.DateTimeFormatOptions = { month: 'long', day: 'numeric' }; + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || '').minus({ day: 1 }); + + if (startTime.toISO() === endTime.toISO()) { + return startTime.toLocaleString(format); + } + + return `${startTime.toLocaleString(format)} - ${endTime.toLocaleString( + format, + )}`; +} + +export function isPassed(event: MicrosoftCalendarEvent) { + if (!event.end?.dateTime) return false; + const eventDate = DateTime.fromISO(event.end?.dateTime!); + return DateTime.now() >= eventDate; +} + +export function isAllDay(event: MicrosoftCalendarEvent) { + const startTime = DateTime.fromISO(event.start?.dateTime || ''); + const endTime = DateTime.fromISO(event.end?.dateTime || ''); + + return endTime.diff(startTime, 'day').days >= 1; +} + +export function getStartDate(event: MicrosoftCalendarEvent) { + return DateTime.fromISO(event.start?.dateTime || ''); +} diff --git a/plugins/microsoft-calendar/src/hooks/index.ts b/plugins/microsoft-calendar/src/hooks/index.ts new file mode 100644 index 0000000000..a10f6a6c3a --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { useCalendarsQuery } from './useCalendarsQuery'; +export { useEventsQuery } from './useEventsQuery'; +export { useSignIn } from './useSignIn'; diff --git a/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts b/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.ts new file mode 100644 index 0000000000..47a7990b58 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useCalendarsQuery.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 { useQuery } from '@tanstack/react-query'; + +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; + +import { microsoftCalendarApiRef } from '../api'; + +type Options = { + enabled: boolean; + refreshTime?: number; +}; + +export const useCalendarsQuery = ({ enabled }: Options) => { + const calendarApi = useApi(microsoftCalendarApiRef); + const errorApi = useApi(errorApiRef); + + return useQuery( + ['calendars-list'], + async () => { + const calendars = []; + const value = await calendarApi.getCalendars(); + calendars.push(...value); + return calendars; + }, + { + enabled, + // old data will be returned if last request was made within 3 mins. + staleTime: 180000, + refetchInterval: 3600000, + onError: () => { + errorApi.post({ + name: 'API error', + message: 'Failed to fetch calendars.', + }); + }, + }, + ); +}; diff --git a/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts new file mode 100644 index 0000000000..5e9dc76812 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useEventsQuery.ts @@ -0,0 +1,61 @@ +/* + * 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 { useQuery } from '@tanstack/react-query'; + +import { useApi } from '@backstage/core-plugin-api'; + +import { microsoftCalendarApiRef } from '../api'; + +type Options = { + calendarId: string; + timeMin: string; + timeMax: string; + enabled?: boolean; + timeZone?: string; + refreshTime?: number; +}; + +export const useEventsQuery = ({ + calendarId, + enabled, + timeMin, + timeMax, + timeZone, +}: Options) => { + const calendarApi = useApi(microsoftCalendarApiRef); + return useQuery( + ['calendarEvents', calendarId, timeMin, timeMax, timeZone], + async () => { + const data = await calendarApi.getEvents( + calendarId, + { + startDateTime: timeMin, + endDateTime: timeMax, + }, + { + Prefer: `outlook.timezone="${timeZone}"`, + }, + ); + return data; + }, + { + cacheTime: 300000, + enabled, + refetchInterval: 60000, + refetchIntervalInBackground: true, + }, + ); +}; diff --git a/plugins/microsoft-calendar/src/hooks/useSignIn.ts b/plugins/microsoft-calendar/src/hooks/useSignIn.ts new file mode 100644 index 0000000000..8b3ac54f92 --- /dev/null +++ b/plugins/microsoft-calendar/src/hooks/useSignIn.ts @@ -0,0 +1,39 @@ +/* + * 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'; + +import { microsoftAuthApiRef, useApi } from '@backstage/core-plugin-api'; + +export const useSignIn = () => { + const [isSignedIn, setSignedIn] = useState(false); + const [isInitialized, setInitialized] = useState(false); + const authApi = useApi(microsoftAuthApiRef); + + const signIn = useCallback( + async (optional = false) => { + const token = await authApi.getAccessToken('Calendars.Read', { + optional, + instantPopup: !optional, + }); + + setSignedIn(!!token); + setInitialized(true); + }, + [authApi, setSignedIn], + ); + + return { isSignedIn, isInitialized, signIn }; +}; diff --git a/plugins/microsoft-calendar/src/icons/calendar.svg b/plugins/microsoft-calendar/src/icons/calendar.svg new file mode 100644 index 0000000000..79895da87a --- /dev/null +++ b/plugins/microsoft-calendar/src/icons/calendar.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/microsoft-calendar/src/icons/webcam.svg b/plugins/microsoft-calendar/src/icons/webcam.svg new file mode 100644 index 0000000000..356bb69215 --- /dev/null +++ b/plugins/microsoft-calendar/src/icons/webcam.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/microsoft-calendar/src/index.ts b/plugins/microsoft-calendar/src/index.ts new file mode 100644 index 0000000000..6867ca31ac --- /dev/null +++ b/plugins/microsoft-calendar/src/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 { MicrosoftCalendarCard } from './plugin'; +export { MicrosoftCalendarApiClient, microsoftCalendarApiRef } from './api'; diff --git a/plugins/microsoft-calendar/src/plugin.test.ts b/plugins/microsoft-calendar/src/plugin.test.ts new file mode 100644 index 0000000000..7da86e176b --- /dev/null +++ b/plugins/microsoft-calendar/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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 { microsoftCalendarPlugin } from './plugin'; + +describe('microsoft-calendar', () => { + it('should export plugin', () => { + expect(microsoftCalendarPlugin).toBeDefined(); + }); +}); diff --git a/plugins/microsoft-calendar/src/plugin.ts b/plugins/microsoft-calendar/src/plugin.ts new file mode 100644 index 0000000000..644d368d97 --- /dev/null +++ b/plugins/microsoft-calendar/src/plugin.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2023 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 { + createPlugin, + microsoftAuthApiRef, + fetchApiRef, + createApiFactory, + createComponentExtension, +} from '@backstage/core-plugin-api'; +import { + microsoftCalendarApiRef, + MicrosoftCalendarApiClient, +} from './api/index'; + +export const microsoftCalendarPlugin = createPlugin({ + id: 'microsoft-calendar', + apis: [ + createApiFactory({ + api: microsoftCalendarApiRef, + deps: { authApi: microsoftAuthApiRef, fetchApi: fetchApiRef }, + factory(deps) { + return new MicrosoftCalendarApiClient(deps); + }, + }), + ], +}); + +/** @public */ +export const MicrosoftCalendarCard = microsoftCalendarPlugin.provide( + createComponentExtension({ + name: 'MicrosoftCalendarCard', + component: { + lazy: () => import('./components').then(m => m.MicrosoftCalendar), + }, + }), +); diff --git a/plugins/microsoft-calendar/src/setupTests.ts b/plugins/microsoft-calendar/src/setupTests.ts new file mode 100644 index 0000000000..73dd8dce47 --- /dev/null +++ b/plugins/microsoft-calendar/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 6d3c0c4e0e..78aadfc390 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 4c4957d400..5fe39fd8a3 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.8-next.0", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 8332f157af..8858555c7c 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-newrelic +## 0.3.33-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.3.33-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.3.32 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 022eda45bd..e02c690eff 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.32", + "version": "0.3.33-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index c01567643b..6af5e01b9b 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-org-react +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.4-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 9752cacd32..6e939b1954 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.4-next.0", + "version": "0.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,7 +36,7 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@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" diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 6612957bdb..31c7843fa4 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-org +## 0.6.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.6.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.6.5-next.0 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 8a2364729c..240e473b88 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.6.5-next.0", + "version": "0.6.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index ef3dc0c0ab..f9424baaea 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-pagerduty +## 0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.5.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.5.8-next.0 ### Patch Changes diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index 7b3124ab0f..98f769e9f3 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -6,7 +6,7 @@ # How it Works - The Backstage PagerDuty plugin allows PagerDuty information about a Backstage entity to be displayed within Backstage. This includes active incidents, recent change events, as well as the current on-call responders' names, email addresses, and links to their profiles in PagerDuty. -- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders. +- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders (Alternatively, the plugin can be configured with an optional `readOnly` property to suppress the ability to trigger incidents from the plugin). - _Note: This feature is only available when providing the `pagerduty.com/integration-key` annotation_ - Change events will be displayed in a separate tab. If the change event payload has additional links the first link only will be rendered. @@ -145,6 +145,24 @@ pagerduty: eventsBaseUrl: 'https://events.pagerduty.com/v2' ``` +To suppress the rendering of the actionable incident-creation button, the `PagerDutyCard` can also be instantiated in `readOnly` mode: + +```ts + +``` + +**WARNING**: In current implementation, the PagerDuty plugin requires the `/pagerduty` proxy endpoint be exposed by the Backstage backend as an unprotected endpoint, in effect enabling PagerDuty API access using the configured `PAGERDUTY_TOKEN` for any user or process with access to the `/pagerduty` Backstage backend endpoint. If you regard this as problematic, consider using the plugin in `readOnly` mode (``) using the following proxy configuration: + +```yaml +proxy: + '/pagerduty': + target: https://api.pagerduty.com + headers: + Authorization: Token token=${PAGERDUTY_TOKEN} + # prohibit the `/pagerduty` proxy endpoint from servicing non-GET requests + allowedMethods: ['GET'] +``` + # How to Uninstall 1. Remove any configuration added in Backstage yaml files, such as the proxy configuration in `app-config.yaml` and the integration key in an entity's annotations. diff --git a/plugins/pagerduty/api-report.md b/plugins/pagerduty/api-report.md index 5bfe84e63f..b460086976 100644 --- a/plugins/pagerduty/api-report.md +++ b/plugins/pagerduty/api-report.md @@ -14,7 +14,7 @@ import { FetchApi } from '@backstage/core-plugin-api'; import { ReactNode } from 'react'; // @public (undocumented) -export const EntityPagerDutyCard: () => JSX.Element; +export const EntityPagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; // @public (undocumented) const isPluginApplicableToEntity: (entity: Entity) => boolean; @@ -45,7 +45,12 @@ export type PagerDutyAssignee = { }; // @public (undocumented) -export const PagerDutyCard: () => JSX.Element; +export const PagerDutyCard: (props: PagerDutyCardProps) => JSX.Element; + +// @public (undocumented) +export type PagerDutyCardProps = { + readOnly?: boolean; +}; // @public (undocumented) export type PagerDutyChangeEvent = { diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 721ff91a53..df20b498ed 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.5.8-next.0", + "version": "0.5.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx index 85202a9cfc..34c8914fde 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.test.tsx @@ -356,4 +356,27 @@ describe('PageDutyCard', () => { expect(getByText('Empty escalation policy')).toBeInTheDocument(); }); }); + + describe('when entity has all annotations but the plugin has been configured to be "read only"', () => { + it('queries by integration key but does not render the "Create Incident" button', async () => { + mockPagerDutyApi.getServiceByEntity = jest + .fn() + .mockImplementationOnce(async () => ({ service })); + + const { getByText, queryByTestId } = render( + wrapInTestApp( + + + + + , + ), + ); + await waitFor(() => !queryByTestId('progress')); + expect(getByText('Service Directory')).toBeInTheDocument(); + expect(getByText('Nice! No incidents found!')).toBeInTheDocument(); + expect(getByText('Empty escalation policy')).toBeInTheDocument(); + expect(() => getByText('Create Incident')).toThrow(); + }); + }); }); diff --git a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx index 15967fae01..fd23166d88 100644 --- a/plugins/pagerduty/src/components/PagerDutyCard/index.tsx +++ b/plugins/pagerduty/src/components/PagerDutyCard/index.tsx @@ -54,7 +54,13 @@ export const isPluginApplicableToEntity = (entity: Entity) => ); /** @public */ -export const PagerDutyCard = () => { +export type PagerDutyCardProps = { + readOnly?: boolean; +}; + +/** @public */ +export const PagerDutyCard = (props: PagerDutyCardProps) => { + const { readOnly } = props; const { entity } = useEntity(); const pagerDutyEntity = getPagerDutyEntity(entity); const api = useApi(pagerDutyApiRef); @@ -156,7 +162,11 @@ export const PagerDutyCard = () => { title="PagerDuty" subheader={ } /> diff --git a/plugins/pagerduty/src/components/index.ts b/plugins/pagerduty/src/components/index.ts index 17bb2c03dc..e7c1ff4e72 100644 --- a/plugins/pagerduty/src/components/index.ts +++ b/plugins/pagerduty/src/components/index.ts @@ -23,6 +23,8 @@ export type { PagerDutyUser, } from './types'; +export type { PagerDutyCardProps } from './PagerDutyCard'; + export { isPluginApplicableToEntity, isPluginApplicableToEntity as isPagerDutyAvailable, diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index d7fd30baab..1e6ff6f307 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-periskop-backend +## 0.1.13-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/periskop-backend/api-report.md b/plugins/periskop-backend/api-report.md index caaed109f9..7906bc4785 100644 --- a/plugins/periskop-backend/api-report.md +++ b/plugins/periskop-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 { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -10,6 +11,9 @@ import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; +// @alpha +export const periskopPlugin: () => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index cee8af1556..419d430fac 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.13-next.0", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,11 +11,12 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -24,6 +25,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@types/express": "*", "express": "^4.17.1", @@ -39,6 +41,7 @@ "supertest": "^6.1.6" }, "files": [ - "dist" + "dist", + "alpha" ] } diff --git a/plugins/periskop-backend/src/index.ts b/plugins/periskop-backend/src/index.ts index ca73cb27ba..a053633745 100644 --- a/plugins/periskop-backend/src/index.ts +++ b/plugins/periskop-backend/src/index.ts @@ -15,3 +15,4 @@ */ export * from './service/router'; +export { periskopPlugin } from './plugin'; diff --git a/plugins/periskop-backend/src/plugin.ts b/plugins/periskop-backend/src/plugin.ts new file mode 100644 index 0000000000..933c864d50 --- /dev/null +++ b/plugins/periskop-backend/src/plugin.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The Periskop backend plugin. + * + * @alpha + */ +export const periskopPlugin = createBackendPlugin({ + pluginId: 'periskop', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, logger, httpRouter }) { + httpRouter.use( + await createRouter({ config, logger: loggerToWinstonLogger(logger) }), + ); + }, + }); + }, +}); diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 6fa77d51d0..eeabe21052 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-periskop +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.1.13-next.0 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 2048df912f..08d875e51f 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.13-next.0", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 0a5e07716b..f8cb24795b 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-permission-backend +## 0.5.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## 0.5.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + ## 0.5.17-next.0 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 66796cb82c..b0b54f6b6e 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.17-next.0", + "version": "0.5.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 2f97a29a70..51c27671db 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-permission-node +## 0.7.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + +## 0.7.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + ## 0.7.5-next.0 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index cc9d98f8fb..c43904fd00 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.7.5-next.0", + "version": "0.7.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index 2ad29e5120..c634e3c2e0 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-playlist-backend +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-playlist-common@0.1.4 + +## 0.2.5-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.2.5-next.0 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 73ef52c5cd..cc3e62eb5a 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.2.5-next.0", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,7 +23,6 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", @@ -43,6 +42,7 @@ "zod": "~3.18.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/supertest": "^2.0.8", "msw": "^0.49.0", diff --git a/plugins/playlist-backend/src/permissions/rules.ts b/plugins/playlist-backend/src/permissions/rules.ts index 99f4725972..e29465ed0f 100644 --- a/plugins/playlist-backend/src/permissions/rules.ts +++ b/plugins/playlist-backend/src/permissions/rules.ts @@ -31,10 +31,10 @@ const createPlaylistPermissionRule = makeCreatePermissionRule< const isOwner = createPlaylistPermissionRule({ name: 'IS_OWNER', - description: 'Should allow only if the playlist belongs to the user', + description: 'Allow playlists owned by the given entity refs', resourceType: PLAYLIST_LIST_RESOURCE_TYPE, paramsSchema: z.object({ - owners: z.array(z.string()).describe('List of owner entity refs'), + owners: z.array(z.string()).describe('List of entity refs to match on'), }), apply: (list: PlaylistMetadata, { owners }) => owners.includes(list.owner), toQuery: ({ owners }) => ({ @@ -45,7 +45,7 @@ const isOwner = createPlaylistPermissionRule({ const isPublic = createPlaylistPermissionRule({ name: 'IS_PUBLIC', - description: 'Should allow only if the playlist is public', + description: 'Allow playlists that are set as public', resourceType: PLAYLIST_LIST_RESOURCE_TYPE, apply: (list: PlaylistMetadata) => list.public, toQuery: () => ({ key: 'public', values: [true] }), diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 9a4c780b1e..ea27ee40f3 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-playlist +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + +## 0.1.6-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-playlist-common@0.1.4 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 2df8e5932d..624fdbcd75 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.6-next.0", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "@backstage/plugin-playlist-common": "workspace:^", "@backstage/plugin-search-react": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", "lodash": "^4.17.21", diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index a0452dff3f..ad235f36e8 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-proxy-backend +## 0.2.36-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## 0.2.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + ## 0.2.36-next.0 ### Patch Changes diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 581e7a904c..741f7c3b54 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-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 { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import express from 'express'; import { Logger } from 'winston'; @@ -11,6 +12,15 @@ import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public export function createRouter(options: RouterOptions): Promise; +// @alpha +export const proxyPlugin: ( + options?: + | { + skipInvalidProxies?: boolean | undefined; + } + | undefined, +) => BackendFeature; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index de45524f25..76440ce0a9 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,14 +1,15 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.36-next.0", + "version": "0.2.36-next.2", "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" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "backstage": { "role": "backend-plugin" @@ -24,7 +25,7 @@ ], "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -33,6 +34,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/config": "workspace:^", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -56,7 +58,8 @@ }, "files": [ "dist", - "config.d.ts" + "config.d.ts", + "alpha" ], "configSchema": "config.d.ts" } diff --git a/plugins/proxy-backend/src/index.ts b/plugins/proxy-backend/src/index.ts index 8f5d5c79dc..2658a557b7 100644 --- a/plugins/proxy-backend/src/index.ts +++ b/plugins/proxy-backend/src/index.ts @@ -21,3 +21,4 @@ */ export * from './service'; +export { proxyPlugin } from './plugin'; diff --git a/plugins/proxy-backend/src/plugin.ts b/plugins/proxy-backend/src/plugin.ts new file mode 100644 index 0000000000..d095bee527 --- /dev/null +++ b/plugins/proxy-backend/src/plugin.ts @@ -0,0 +1,53 @@ +/* + * Copyright 2023 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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The proxy backend plugin. + * + * @alpha + */ +export const proxyPlugin = createBackendPlugin( + (options?: { skipInvalidProxies?: boolean }) => ({ + pluginId: 'proxy', + register(env) { + env.registerInit({ + deps: { + config: coreServices.config, + discovery: coreServices.discovery, + logger: coreServices.logger, + httpRouter: coreServices.httpRouter, + }, + async init({ config, discovery, logger, httpRouter }) { + httpRouter.use( + await createRouter({ + config, + discovery, + logger: loggerToWinstonLogger(logger), + skipInvalidProxies: options?.skipInvalidProxies, + }), + ); + }, + }); + }, + }), +); diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index a9df1c2eea..9e6955c033 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-rollbar-backend +## 0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + +## 0.1.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + ## 0.1.39-next.0 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index d481ad0217..876c797a78 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.39-next.0", + "version": "0.1.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 629fc36e26..1fe3b3d6ba 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-rollbar +## 0.4.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.4.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.4.15-next.0 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index bea1cab9ee..2d65565015 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.4.15-next.0", + "version": "0.4.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 60628eb84d..65121ebda8 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index f1024a1fa9..669f498c1e 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.2.17-next.0", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index b705593493..51a6a9b796 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-scaffolder-backend@1.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + +## 0.4.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/plugin-scaffolder-backend@1.11.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + ## 0.4.10-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index f096eeb379..1e4d881ef0 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.4.10-next.0", + "version": "0.4.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 84140cd106..9a7df7e14b 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.1.2-next.1 + +### Patch Changes + +- da418c89e4: Fix broken module exports and dependencies to match a backend module, rather than a frontend plugin. +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 95a89371c8..903ad54dc1 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.2-next.0", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index ebc657b508..5c4acbd85c 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 993a80c304..7ae88b60e6 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.2.15-next.0", + "version": "0.2.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 9bc5fc1e34..d6db10f4ae 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/plugin-scaffolder-backend +## 1.11.0-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-catalog-backend@1.7.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.2 + - @backstage/plugin-scaffolder-node@0.1.0-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## 1.11.0-next.1 + +### Minor Changes + +- 127154930f: Renamed the export `scaffolderCatalogModule` to `catalogModuleTemplateKind` in order to follow the new recommended naming patterns of backend system items. This is technically a breaking change but in an alpha export, so take care to change your imports if you have already migrated to the new backend system. + +### Patch Changes + +- 66cf22fdc4: Updated dependency `esbuild` to `^0.17.0`. +- Updated dependencies + - @backstage/plugin-catalog-backend@1.7.2-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-catalog-node@1.3.3-next.1 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + - @backstage/plugin-scaffolder-node@0.1.0-next.1 + ## 1.11.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 6098fdc537..ccc586f55b 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": "1.11.0-next.0", + "version": "1.11.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/scripts/build-nunjucks.js b/plugins/scaffolder-backend/scripts/build-nunjucks.js index 8b98ac4305..8183de77ee 100755 --- a/plugins/scaffolder-backend/scripts/build-nunjucks.js +++ b/plugins/scaffolder-backend/scripts/build-nunjucks.js @@ -16,7 +16,7 @@ */ /* eslint-disable no-restricted-syntax */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const path = require('path'); diff --git a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts index 43b8d30f99..3b0d26be21 100644 --- a/plugins/scaffolder-backend/src/ScaffolderPlugin.ts +++ b/plugins/scaffolder-backend/src/ScaffolderPlugin.ts @@ -64,7 +64,7 @@ class ScaffolderActionsExtensionPointImpl */ export const scaffolderPlugin = createBackendPlugin( (options: ScaffolderPluginOptions) => ({ - id: 'scaffolder', + pluginId: 'scaffolder', register(env) { const actionsExtensions = new ScaffolderActionsExtensionPointImpl(); diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 4b7444994a..e1936292f9 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-common +## 1.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + ## 1.2.5-next.0 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index bf8c32d5d1..3ec3528427 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": "1.2.5-next.0", + "version": "1.2.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index a447f09770..cd2ef0259e 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-node +## 0.1.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## 0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.3.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/types@1.0.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index f67fe89623..ce82f57f5f 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.1.0-next.0", + "version": "0.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index c57b102949..51fa1abc63 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-scaffolder-react +## 1.1.0-next.2 + +### Minor Changes + +- 5555e17313: refactor `createAsyncValidators` to be recursive to ensure validators are called in nested schemas. + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## 1.1.0-next.1 + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + ## 1.1.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index deead4366c..72a0b92eef 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -85,6 +85,11 @@ export type CustomFieldValidator = ( }, ) => void | Promise; +// @alpha +export const DefaultTemplateOutputs: (props: { + output?: ScaffolderTaskOutput; +}) => JSX.Element | null; + // @alpha (undocumented) export const EmbeddableWorkflow: (props: WorkflowProps) => JSX.Element; diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 4667216af7..e26bd973d5 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.1.0-next.0", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,11 +47,11 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@rjsf/core": "^3.2.1", - "@rjsf/core-v5": "npm:@rjsf/core@5.0.1", + "@rjsf/core-v5": "npm:@rjsf/core@5.1.0", "@rjsf/material-ui": "^3.2.1", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.0.1", - "@rjsf/utils": "5.0.1", - "@rjsf/validator-ajv8": "5.0.1", + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.1.0", + "@rjsf/utils": "5.1.0", + "@rjsf/validator-ajv8": "5.1.0", "@types/json-schema": "^7.0.9", "classnames": "^2.2.6", "json-schema": "^0.4.0", diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index c97d31c487..f802121597 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -23,11 +23,14 @@ import { makeStyles, } from '@material-ui/core'; import { type IChangeEvent, withTheme } from '@rjsf/core-v5'; -import { ErrorSchema, FieldValidation } from '@rjsf/utils'; +import { ErrorSchema } from '@rjsf/utils'; import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; import { NextFieldExtensionOptions } from '../../extensions'; import { TemplateParameterSchema } from '../../../types'; -import { createAsyncValidators } from './createAsyncValidators'; +import { + createAsyncValidators, + type FormValidation, +} from './createAsyncValidators'; import { ReviewState, type ReviewStateProps } from '../ReviewState'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv8'; @@ -35,6 +38,7 @@ import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; import { LayoutOptions } from '../../../layouts'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; +import { hasErrors } from './utils'; const useStyles = makeStyles(theme => ({ backButton: { @@ -92,9 +96,7 @@ export const Stepper = (stepperProps: StepperProps) => { const [activeStep, setActiveStep] = useState(0); const [formState, setFormState] = useFormDataFromQuery(props.initialState); - const [errors, setErrors] = useState< - undefined | Record - >(); + const [errors, setErrors] = useState(); const styles = useStyles(); const extensions = useMemo(() => { @@ -125,6 +127,8 @@ export const Stepper = (stepperProps: StepperProps) => { [setFormState], ); + const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); + const handleNext = async ({ formData = {}, }: { @@ -136,11 +140,7 @@ export const Stepper = (stepperProps: StepperProps) => { const returnedValidation = await validation(formData); - const hasErrors = Object.values(returnedValidation).some( - i => i.__errors?.length, - ); - - if (hasErrors) { + if (hasErrors(returnedValidation)) { setErrors(returnedValidation); } else { setErrors(undefined); @@ -153,8 +153,6 @@ export const Stepper = (stepperProps: StepperProps) => { setFormState(current => ({ ...current, ...formData })); }; - const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); - return ( <> diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 6ad14e3cc4..fe8b41a9f3 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -154,4 +154,122 @@ describe('createAsyncValidators', () => { }), }); }); + + it('should run validation on complex nested schemas', async () => { + const schema: JsonObject = { + title: 'Select component', + properties: { + actionType: { + title: 'action type', + type: 'string', + description: 'Select the action type', + enum: ['newThing', 'existingThing'], + enumNames: ['New thing', 'Existing thing'], + default: 'newThing', + }, + }, + required: ['actionType'], + dependencies: { + actionType: { + oneOf: [ + { + properties: { + actionType: { + enum: ['newThing'], + }, + general: { + title: 'General', + type: 'object', + properties: { + address: { + type: 'object', + 'ui:field': 'AddressField', + properties: { + street: { + type: 'string', + }, + postcode: { + type: 'string', + }, + }, + }, + name: { + title: 'Name', + type: 'string', + 'ui:field': 'NameField', + }, + }, + }, + }, + }, + { + properties: { + actionType: { + enum: ['existingThing'], + }, + thingId: { + title: 'Thing id', + type: 'string', + description: 'Enter thing id', + }, + }, + }, + ], + }, + }, + }; + + const AddressField: NextCustomFieldValidator<{ + street?: string; + postcode?: string; + }> = (value, { addError }) => { + if (!value.postcode) { + addError('postcode is missing!'); + } + + if (!value.street) { + addError('street is missing here!'); + } + }; + + const NameField: NextCustomFieldValidator = ( + value, + { addError }, + ) => { + if (!value) { + addError('something is broken here!'); + } + }; + + const validators = { + AddressField: AddressField as NextCustomFieldValidator, + NameField: NameField as NextCustomFieldValidator, + }; + + const validate = createAsyncValidators(schema, validators, { + apiHolder: { get: jest.fn() }, + }); + + await expect( + validate({ + actionType: 'newThing', + general: { + address: { + street: 'street', + postcode: 'postcode', + }, + name: undefined, + }, + }), + ).resolves.toEqual({ + general: { + address: expect.objectContaining({ + __errors: [], + }), + name: expect.objectContaining({ + __errors: ['something is broken here!'], + }), + }, + }); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 79466ee602..86b7619b34 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -15,11 +15,19 @@ */ import { FieldValidation } from '@rjsf/utils'; -import { JsonObject } from '@backstage/types'; +import type { JsonObject } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation } from '../../lib'; import { NextCustomFieldValidator } from '../../extensions'; +import { isObject } from './utils'; + +/** + * @internal + */ +export type FormValidation = { + [name: string]: FieldValidation | FormValidation; +}; export const createAsyncValidators = ( rootSchema: JsonObject, @@ -28,14 +36,17 @@ export const createAsyncValidators = ( apiHolder: ApiHolder; }, ) => { - async function validate(formData: JsonObject, pathPrefix: string = '#') { + async function validate( + formData: JsonObject, + pathPrefix: string = '#', + current: JsonObject = formData, + ): Promise { const parsedSchema = new JSONSchema(rootSchema); - const formValidation: Record = {}; - for (const [key, value] of Object.entries(formData)) { - const definitionInSchema = parsedSchema.getSchema( - `${pathPrefix}/${key}`, - formData, - ); + const formValidation: FormValidation = {}; + + for (const [key, value] of Object.entries(current)) { + const path = `${pathPrefix}/${key}`; + const definitionInSchema = parsedSchema.getSchema(path, formData); if (definitionInSchema && 'ui:field' in definitionInSchema) { const validator = validators[definitionInSchema['ui:field']]; @@ -48,6 +59,8 @@ export const createAsyncValidators = ( } formValidation[key] = fieldValidation; } + } else if (isObject(value)) { + formValidation[key] = await validate(formData, path, value); } } diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts new file mode 100644 index 0000000000..f6a1b012ac --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.test.ts @@ -0,0 +1,61 @@ +/* + * Copyright 2023 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 { hasErrors } from './utils'; + +describe('hasErrors', () => { + it('should return false for empty _errors', () => { + expect( + hasErrors({ + name: { + __errors: [], + addError: jest.fn(), + }, + }), + ).toBe(false); + }); + + it('should return true for a single error', () => { + expect( + hasErrors({ + name: { + __errors: ['an error'], + addError: jest.fn(), + }, + }), + ).toBe(true); + }); + + it('should return true for more than one error', () => { + expect( + hasErrors({ + name: { + __errors: [], + addError: jest.fn(), + }, + general: { + address: { + __errors: [], + addError: jest.fn(), + }, + name: { + __errors: ['something is broken here!'], + addError: jest.fn(), + }, + }, + }), + ).toBe(true); + }); +}); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/utils.ts b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts new file mode 100644 index 0000000000..7d3efa9d94 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/Stepper/utils.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2023 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 type { JsonObject, JsonValue } from '@backstage/types'; +import type { FieldValidation } from '@rjsf/utils'; +import { FormValidation } from './createAsyncValidators'; + +function isFieldValidation(error: any): error is FieldValidation { + return !!error && '__errors' in error; +} + +export function hasErrors(errors?: FormValidation): boolean { + if (!errors) { + return false; + } + + for (const error of Object.values(errors)) { + if (isFieldValidation(error)) { + if ((error.__errors ?? []).length > 0) { + return true; + } + + continue; + } + + return hasErrors(error); + } + + return false; +} + +export function isObject(value: JsonValue | undefined): value is JsonObject { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx new file mode 100644 index 0000000000..5fbd3a5142 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/DefaultTemplateOutputs.tsx @@ -0,0 +1,42 @@ +/* + * Copyright 2023 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 { Box, Paper } from '@material-ui/core'; +import { LinkOutputs } from './LinkOutputs'; +import { ScaffolderTaskOutput } from '../../../api'; + +/** + * The DefaultOutputs renderer for the scaffolder task output + * + * @alpha + */ +export const DefaultTemplateOutputs = (props: { + output?: ScaffolderTaskOutput; +}) => { + if (!props.output?.links) { + return null; + } + + return ( + + + + + + + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx new file mode 100644 index 0000000000..d172aa9cb3 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/LinkOutputs.tsx @@ -0,0 +1,66 @@ +/* + * Copyright 2023 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 { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { Button, makeStyles } from '@material-ui/core'; +import React from 'react'; +import WebIcon from '@material-ui/icons/Web'; +import { parseEntityRef } from '@backstage/catalog-model'; +import { Link } from '@backstage/core-components'; +import { ScaffolderTaskOutput } from '../../../api'; + +const useStyles = makeStyles({ + root: { + '&:hover': { + textDecoration: 'none', + }, + }, +}); + +export const LinkOutputs = (props: { output: ScaffolderTaskOutput }) => { + const { links = [] } = props.output; + const classes = useStyles(); + const app = useApp(); + const entityRoute = useRouteRef(entityRouteRef); + + const iconResolver = (key?: string): IconComponent => + app.getSystemIcon(key!) ?? WebIcon; + + return ( + <> + {links + .filter(({ url, entityRef }) => url || entityRef) + .map(({ url, entityRef, title, icon }) => { + if (entityRef) { + const entityName = parseEntityRef(entityRef); + const target = entityRoute(entityName); + return { title, icon, url: target }; + } + return { title, icon, url: url! }; + }) + .map(({ url, title, icon }, i) => { + const Icon = iconResolver(icon); + return ( + + + + ); + })} + + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts new file mode 100644 index 0000000000..1c998eb1b9 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateOutputs/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { DefaultTemplateOutputs } from './DefaultTemplateOutputs'; diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index babe3b4dcb..05e5a1105a 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -18,3 +18,4 @@ export * from './TemplateCard'; export * from './ReviewState'; export * from './TemplateGroup'; export * from './Workflow'; +export * from './TemplateOutputs'; diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index d343d4e224..37da3b63e1 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-scaffolder +## 1.11.0-next.2 + +### Patch Changes + +- b46f385eff: scaffolder/next: Implementing a simple `OngoingTask` page +- ccbf91051b: bump `@rjsf` `v5` dependencies to 5.1.0 +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.1 + +## 1.11.0-next.1 + +### Patch Changes + +- 04f717a8e1: `scaffolder/next`: bump `react-jsonschema-form` libraries to `v5-stable` +- 346d6b6630: Upgrade `@rjsf` version 5 dependencies to `beta.18` +- 0f0da2f256: Prefer schema ordering of template properties during review content generation. +- 38992bdbaf: Fixed bug in review step refactor that caused schema-based display settings for individual property values to be discarded. +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.1.0-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-react@0.4.9 + - @backstage/plugin-scaffolder-common@1.2.5-next.0 + ## 1.11.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 1fb72b0fac..43b885b81a 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -197,9 +197,17 @@ export type NextRouterProps = { template: TemplateEntityV1beta3; }>; TaskPageComponent?: React_2.ComponentType<{}>; + TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; }; groups?: TemplateGroupFilter[]; FormProps?: FormProps_2; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; }; // @alpha diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index ae79a35f7c..86f9100deb 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": "1.11.0-next.0", + "version": "1.11.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -57,7 +57,7 @@ "@react-hookz/web": "^20.0.0", "@rjsf/core": "^3.2.1", "@rjsf/material-ui": "^3.2.1", - "@rjsf/utils": "5.0.1", + "@rjsf/utils": "5.1.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx index 1bcf06eee7..112b96bdf1 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx @@ -25,36 +25,38 @@ export function getReviewData( uiSchemas: UiSchema[], ) { const reviewData: Record = {}; - for (const key in formData) { - if (formData.hasOwnProperty(key)) { - const uiSchema = uiSchemas.find(us => us.name === key); + const orderedReviewProperties = new Set( + uiSchemas.map(us => us.name).concat(Object.getOwnPropertyNames(formData)), + ); - if (!uiSchema) { - reviewData[key] = formData[key]; - continue; - } + for (const key of orderedReviewProperties) { + const uiSchema = uiSchemas.find(us => us.name === key); - if (uiSchema['ui:widget'] === 'password') { - reviewData[key] = '******'; - continue; - } - - if (!uiSchema['ui:backstage'] || !uiSchema['ui:backstage'].review) { - reviewData[key] = formData[key]; - continue; - } - - const review = uiSchema['ui:backstage'].review as JsonObject; - if (review.mask) { - reviewData[key] = review.mask; - continue; - } - - if (!review.show) { - continue; - } + if (!uiSchema) { reviewData[key] = formData[key]; + continue; } + + if (uiSchema['ui:widget'] === 'password') { + reviewData[key] = '******'; + continue; + } + + if (!uiSchema['ui:backstage'] || !uiSchema['ui:backstage'].review) { + reviewData[key] = formData[key]; + continue; + } + + const review = uiSchema['ui:backstage'].review as JsonObject; + if (review.mask) { + reviewData[key] = review.mask; + continue; + } + + if (!review.show) { + continue; + } + reviewData[key] = formData[key]; } return reviewData; diff --git a/plugins/scaffolder/src/components/hooks/useEventStream.ts b/plugins/scaffolder/src/components/hooks/useEventStream.ts index 0b36c85ad8..be0ff922a4 100644 --- a/plugins/scaffolder/src/components/hooks/useEventStream.ts +++ b/plugins/scaffolder/src/components/hooks/useEventStream.ts @@ -25,7 +25,7 @@ import { import { useApi } from '@backstage/core-plugin-api'; import { Subscription } from '@backstage/types'; -type Step = { +export type Step = { id: string; status: ScaffolderTaskStatus; endedAt?: string; diff --git a/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx new file mode 100644 index 0000000000..d4c771a9f8 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx @@ -0,0 +1,87 @@ +/* + * Copyright 2023 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 { BackstageTheme } from '@backstage/theme'; +import { + IconButton, + ListItemIcon, + ListItemText, + makeStyles, + MenuItem, + MenuList, + Popover, +} from '@material-ui/core'; +import Retry from '@material-ui/icons/Repeat'; +import Toc from '@material-ui/icons/Toc'; +import MoreVert from '@material-ui/icons/MoreVert'; +import React, { useState } from 'react'; + +type ContextMenuProps = { + logsVisible?: boolean; + onToggleLogs?: (state: boolean) => void; + onStartOver?: () => void; +}; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + button: { + color: theme.palette.common.white, + }, +})); + +export const ContextMenu = (props: ContextMenuProps) => { + const { logsVisible, onToggleLogs, onStartOver } = props; + const classes = useStyles(); + const [anchorEl, setAnchorEl] = useState(); + + return ( + <> + ) => { + setAnchorEl(event.currentTarget); + }} + data-testid="menu-button" + color="inherit" + className={classes.button} + > + + + setAnchorEl(undefined)} + anchorEl={anchorEl} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + + onToggleLogs?.(!logsVisible)}> + + + + + + + + + + + + + + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx new file mode 100644 index 0000000000..a68df01ed5 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx @@ -0,0 +1,160 @@ +/* + * Copyright 2023 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, { useEffect, useMemo, useState, useCallback } from 'react'; +import { Page, Header, Content, ErrorPanel } from '@backstage/core-components'; +import { useTaskEventStream } from '../../components/hooks/useEventStream'; +import { useNavigate, useParams } from 'react-router-dom'; +import { Box, makeStyles, Paper } from '@material-ui/core'; +import { TaskSteps } from './TaskSteps'; +import { TaskBorder } from './TaskBorder'; +import { TaskLogStream } from './TaskLogStream'; +import { nextSelectedTemplateRouteRef } from '../routes'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import qs from 'qs'; +import { ContextMenu } from './ContextMenu'; +import { + DefaultTemplateOutputs, + ScaffolderTaskOutput, +} from '@backstage/plugin-scaffolder-react'; + +const useStyles = makeStyles({ + contentWrapper: { + display: 'flex', + flexDirection: 'column', + }, +}); + +export const OngoingTask = (props: { + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; +}) => { + // todo(blam): check that task Id actually exists, and that it's valid. otherwise redirect to something more useful. + const { taskId } = useParams(); + const templateRouteRef = useRouteRef(nextSelectedTemplateRouteRef); + const navigate = useNavigate(); + const taskStream = useTaskEventStream(taskId!); + const classes = useStyles(); + const steps = useMemo( + () => + taskStream.task?.spec.steps.map(step => ({ + ...step, + ...taskStream?.steps?.[step.id], + })) ?? [], + [taskStream], + ); + + const [logsVisible, setLogVisibleState] = useState(false); + + useEffect(() => { + if (taskStream.error) { + setLogVisibleState(true); + } + }, [taskStream.error]); + + const activeStep = useMemo(() => { + for (let i = steps.length - 1; i >= 0; i--) { + if (steps[i].status !== 'open') { + return i; + } + } + + return 0; + }, [steps]); + + const startOver = useCallback(() => { + const { namespace, name } = + taskStream.task?.spec.templateInfo?.entity?.metadata ?? {}; + + const formData = taskStream.task?.spec.parameters ?? {}; + + if (!namespace || !name) { + return; + } + + navigate({ + pathname: templateRouteRef({ + namespace, + templateName: name, + }), + search: `?${qs.stringify({ formData: JSON.stringify(formData) })}`, + }); + }, [ + navigate, + taskStream.task?.spec.parameters, + taskStream.task?.spec.templateInfo?.entity?.metadata, + templateRouteRef, + ]); + + const Outputs = props.TemplateOutputsComponent ?? DefaultTemplateOutputs; + + const templateName = + taskStream.task?.spec.templateInfo?.entity?.metadata.name; + + return ( + +
    + Run of {templateName} +
  • + } + subtitle={`Task ${taskId}`} + > + +
    + + {taskStream.error ? ( + + + + ) : null} + + + + + + + + + + + + + {logsVisible ? ( + + + + + + + + ) : null} + + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx new file mode 100644 index 0000000000..f3a59ad344 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.test.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { TaskBorder } from './TaskBorder'; +import { render } from '@testing-library/react'; + +describe('TaskBorder', () => { + it('should render a pending linear progress if the task is not complete', () => { + const { getByRole } = render( + , + ); + + const progressBar = getByRole('progressbar'); + + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveClass('MuiLinearProgress-indeterminate'); + }); + + it('should render a determinate progress bar if the task is complete', () => { + const { getByRole } = render(); + + const progressBar = getByRole('progressbar'); + + expect(progressBar).toBeInTheDocument(); + expect(progressBar).toHaveClass('MuiLinearProgress-determinate'); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx new file mode 100644 index 0000000000..fdfab17367 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskBorder.tsx @@ -0,0 +1,46 @@ +/* + * Copyright 2023 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 { LinearProgress, makeStyles } from '@material-ui/core'; +import { BackstageTheme } from '@backstage/theme'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + failed: { + backgroundColor: theme.palette.error.main, + }, + success: { + backgroundColor: theme.palette.success.main, + }, +})); + +export const TaskBorder = (props: { + isComplete: boolean; + isError: boolean; +}) => { + const styles = useStyles(); + + if (!props.isComplete) { + return ; + } + + return ( + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx new file mode 100644 index 0000000000..e8f9e67e96 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.test.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2023 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 { renderInTestApp } from '@backstage/test-utils'; +import React, { ReactNode } from 'react'; +import { TaskLogStream } from './TaskLogStream'; + +// The inside needs mocking to render in jsdom +jest.mock('react-virtualized-auto-sizer', () => ({ + __esModule: true, + default: (props: { + children: (size: { width: number; height: number }) => ReactNode; + }) => <>{props.children({ width: 400, height: 200 })}, +})); + +describe('TaskLogStream', () => { + it('should render a log stream with the correct log lines', async () => { + const logs = { step: ['line 1', 'line 2'], step2: ['line 3'] }; + + const { findByText } = await renderInTestApp(); + + const logLines = Object.values(logs).flat(); + + for (const line of logLines) { + await expect(findByText(line)).resolves.toBeInTheDocument(); + } + }); + + it('should filter out empty log lines', async () => { + const logs = { step: ['line 1', 'line 2'], step2: [] }; + + const { findAllByRole } = await renderInTestApp( + , + ); + + await expect(findAllByRole('row')).resolves.toHaveLength(2); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx new file mode 100644 index 0000000000..00e8452b42 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskLogStream.tsx @@ -0,0 +1,40 @@ +/* + * Copyright 2023 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 { LogViewer } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles({ + root: { + width: '100%', + height: '100%', + position: 'relative', + }, +}); + +export const TaskLogStream = (props: { logs: { [k: string]: string[] } }) => { + const styles = useStyles(); + return ( +
    + l.join('\n')) + .filter(Boolean) + .join('\n')} + /> +
    + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx new file mode 100644 index 0000000000..cecf682596 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepIcon.tsx @@ -0,0 +1,71 @@ +/* + * Copyright 2023 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 { BackstageTheme } from '@backstage/theme'; +import { CircularProgress, makeStyles, StepIconProps } from '@material-ui/core'; +import RemoveCircleOutline from '@material-ui/icons/RemoveCircleOutline'; +import PanoramaFishEyeIcon from '@material-ui/icons/PanoramaFishEye'; +import classNames from 'classnames'; +import CheckCircleOutline from '@material-ui/icons/CheckCircleOutline'; +import ErrorOutline from '@material-ui/icons/ErrorOutline'; + +const useStepIconStyles = makeStyles((theme: BackstageTheme) => ({ + root: { + color: theme.palette.text.disabled, + }, + completed: { + color: theme.palette.status.ok, + }, + error: { + color: theme.palette.status.error, + }, +})); + +export const StepIcon = (props: StepIconProps & { skipped: boolean }) => { + const classes = useStepIconStyles(); + const { active, completed, error, skipped } = props; + + const getMiddle = () => { + if (active) { + return ; + } + if (completed) { + return ; + } + + if (error) { + return ; + } + + if (skipped) { + return ; + } + + return ; + }; + + return ( +
    + {getMiddle()} +
    + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx new file mode 100644 index 0000000000..185d2fa7fb --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.test.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2023 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 { StepTime } from './StepTime'; +import { render, act } from '@testing-library/react'; + +describe('StepTime', () => { + it('should return empty when there is no start time', () => { + const step = { + id: 'test', + startedAt: undefined, + endedAt: undefined, + name: 'test', + }; + + const { container } = render(); + + expect(container.querySelector('span')?.textContent).toBe(''); + }); + + it('should format the time between the start and end date properly', async () => { + const step = { + id: 'test', + startedAt: '2021-01-01T00:00:00Z', + endedAt: '2021-01-01T00:00:01Z', + name: 'test', + }; + + const { findByText } = render(); + + await expect(findByText('1 second')).resolves.toBeInTheDocument(); + }); + + describe('updates', () => { + beforeEach(() => { + jest.useFakeTimers({ now: new Date('2021-01-01T00:00:00Z') }); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it('should update the time every second', async () => { + const step = { + id: 'test', + startedAt: '2021-01-01T00:00:00Z', + endedAt: undefined, + name: 'test', + }; + + const { findByText } = render(); + + await expect(findByText('0 seconds')).resolves.toBeInTheDocument(); + + act(() => jest.advanceTimersByTime(1000)); + + await expect(findByText('1 second')).resolves.toBeInTheDocument(); + + act(() => jest.advanceTimersByTime(1000 * 60)); + + await expect( + findByText('1 minute, 1 second'), + ).resolves.toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx new file mode 100644 index 0000000000..653fe6e942 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/StepTime.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2023 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, { useCallback, useState } from 'react'; +import useInterval from 'react-use/lib/useInterval'; +import { DateTime, Interval } from 'luxon'; +import humanizeDuration from 'humanize-duration'; +import { Typography } from '@material-ui/core'; +import { useMountEffect } from '@react-hookz/web'; + +export const StepTime = (props: { + step: { + id: string; + name: string; + startedAt?: string; + endedAt?: string; + }; +}) => { + const [time, setTime] = useState(''); + const { step } = props; + + const calculate = useCallback(() => { + if (!step.startedAt) { + setTime(''); + return; + } + + const end = step.endedAt + ? DateTime.fromISO(step.endedAt) + : DateTime.local(); + + const startedAt = DateTime.fromISO(step.startedAt); + const formatted = Interval.fromDateTimes(startedAt, end) + .toDuration() + .valueOf(); + + setTime(humanizeDuration(formatted, { round: true })); + }, [step.endedAt, step.startedAt]); + + useMountEffect(() => calculate()); + + useInterval(() => !step.endedAt && calculate(), 1000); + + return {time}; +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx new file mode 100644 index 0000000000..afd1f58190 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright 2023 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 { TaskSteps } from './TaskSteps'; +import { ScaffolderTaskStatus } from '@backstage/plugin-scaffolder-react'; +import { renderInTestApp } from '@backstage/test-utils'; + +describe('TaskSteps', () => { + it('should render each of the steps', async () => { + const steps = [ + { + id: '1', + name: 'Step 1', + status: 'processing' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '2', + name: 'Step 2', + status: 'failed' as ScaffolderTaskStatus, + + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '3', + name: 'Step 3', + status: 'completed' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + { + id: '4', + name: 'Step 4', + status: 'skipped' as ScaffolderTaskStatus, + startedAt: Date.now().toLocaleString(), + endedAt: Date.now().toLocaleString(), + action: 'create', + }, + ]; + + const { getByText } = await renderInTestApp(); + + for (const step of steps) { + expect(getByText(step.name)).toBeInTheDocument(); + } + }); +}); diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx new file mode 100644 index 0000000000..7cf5ed71bf --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/TaskSteps.tsx @@ -0,0 +1,70 @@ +/* + * 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 { + Stepper as MuiStepper, + Step as MuiStep, + StepButton as MuiStepButton, + StepLabel as MuiStepLabel, + StepIconProps, + Box, +} from '@material-ui/core'; +import { TaskStep } from '@backstage/plugin-scaffolder-common'; +import { Step } from '../../../components/hooks/useEventStream'; +import { StepIcon } from './StepIcon'; +import { StepTime } from './StepTime'; + +interface StepperProps { + steps: (TaskStep & Step)[]; + activeStep?: number; +} + +export const TaskSteps = (props: StepperProps) => { + return ( + + {props.steps.map((step, index) => { + const isCompleted = step.status === 'completed'; + const isFailed = step.status === 'failed'; + const isActive = step.status === 'processing'; + const isSkipped = step.status === 'skipped'; + const stepIconProps: Partial = { + completed: isCompleted, + error: isFailed, + active: isActive, + skipped: isSkipped, + }; + + return ( + + + + {step.name} + + + + + ); + })} + + ); +}; diff --git a/plugins/scaffolder/src/next/OngoingTask/TaskSteps/index.ts b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/index.ts new file mode 100644 index 0000000000..28724ba512 --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/TaskSteps/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { TaskSteps } from './TaskSteps'; diff --git a/plugins/scaffolder/src/next/OngoingTask/index.ts b/plugins/scaffolder/src/next/OngoingTask/index.ts new file mode 100644 index 0000000000..f0c7e2a6cc --- /dev/null +++ b/plugins/scaffolder/src/next/OngoingTask/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 { OngoingTask } from './OngoingTask'; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 8dd47b478e..049579e16c 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -19,6 +19,7 @@ import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { NextFieldExtensionOptions, + ScaffolderTaskOutput, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, @@ -28,7 +29,17 @@ import { import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; -import { nextSelectedTemplateRouteRef } from '../routes'; + +import { + nextActionsRouteRef, + nextScaffolderListTaskRouteRef, + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, +} from '../routes'; +import { ErrorPage } from '@backstage/core-components'; +import { OngoingTask } from '../OngoingTask'; +import { ActionsPage } from '../../components/ActionsPage'; +import { ListTasksPage } from '../../components/ListTasksPage'; /** * The Props for the Scaffolder Router @@ -41,9 +52,21 @@ export type NextRouterProps = { template: TemplateEntityV1beta3; }>; TaskPageComponent?: React.ComponentType<{}>; + TemplateOutputsComponent?: React.ComponentType<{ + output?: ScaffolderTaskOutput; + }>; }; groups?: TemplateGroupFilter[]; + // todo(blam): rename this to formProps FormProps?: FormProps; + contextMenu?: { + /** Whether to show a link to the template editor */ + editor?: boolean; + /** Whether to show a link to the actions documentation */ + actions?: boolean; + /** Whether to show a link to the tasks page */ + tasks?: boolean; + }; }; /** @@ -52,10 +75,17 @@ export type NextRouterProps = { * @alpha */ export const Router = (props: PropsWithChildren) => { - const { components: { TemplateCardComponent } = {} } = props; + const { + components: { + TemplateCardComponent, + TemplateOutputsComponent, + TaskPageComponent = OngoingTask, + } = {}, + } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = useCustomFieldExtensions(outlet); + const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -75,6 +105,7 @@ export const Router = (props: PropsWithChildren) => { element={ } @@ -91,6 +122,23 @@ export const Router = (props: PropsWithChildren) => { } /> + + } + /> + } /> + } + /> + } + /> ); }; diff --git a/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx b/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx new file mode 100644 index 0000000000..3bca46af2a --- /dev/null +++ b/plugins/scaffolder/src/next/TemplateListPage/ContextMenu.tsx @@ -0,0 +1,123 @@ +/* + * 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 { useRouteRef } from '@backstage/core-plugin-api'; +import IconButton from '@material-ui/core/IconButton'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText from '@material-ui/core/ListItemText'; +import MenuItem from '@material-ui/core/MenuItem'; +import MenuList from '@material-ui/core/MenuList'; +import Popover from '@material-ui/core/Popover'; +import { makeStyles } from '@material-ui/core/styles'; +import Description from '@material-ui/icons/Description'; +import Edit from '@material-ui/icons/Edit'; +import List from '@material-ui/icons/List'; +import MoreVert from '@material-ui/icons/MoreVert'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { + nextActionsRouteRef, + nextEditRouteRef, + nextScaffolderListTaskRouteRef, +} from '../routes'; + +const useStyles = makeStyles({ + button: { + color: 'white', + }, +}); + +export type ScaffolderPageContextMenuProps = { + editor?: boolean; + actions?: boolean; + tasks?: boolean; +}; + +export function ContextMenu(props: ScaffolderPageContextMenuProps) { + const classes = useStyles(); + const [anchorEl, setAnchorEl] = useState(); + const editLink = useRouteRef(nextEditRouteRef); + const actionsLink = useRouteRef(nextActionsRouteRef); + const tasksLink = useRouteRef(nextScaffolderListTaskRouteRef); + + const navigate = useNavigate(); + + const showEditor = props.editor !== false; + const showActions = props.actions !== false; + const showTasks = props.tasks !== false; + + if (!showEditor && !showActions) { + return null; + } + + const onOpen = (event: React.SyntheticEvent) => { + setAnchorEl(event.currentTarget); + }; + + const onClose = () => { + setAnchorEl(undefined); + }; + + return ( + <> + + + + + + {showEditor && ( + navigate(editLink())}> + + + + + + )} + {showActions && ( + navigate(actionsLink())}> + + + + + + )} + {showTasks && ( + navigate(tasksLink())}> + + + + + + )} + + + + ); +} diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 4eae84b866..b701ceb3c4 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -37,12 +37,18 @@ import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; import { registerComponentRouteRef } from '../../routes'; +import { ContextMenu } from './ContextMenu'; export type TemplateListPageProps = { TemplateCardComponent?: React.ComponentType<{ template: TemplateEntityV1beta3; }>; groups?: TemplateGroupFilter[]; + contextMenu?: { + editor?: boolean; + actions?: boolean; + tasks?: boolean; + }; }; const defaultGroup: TemplateGroupFilter = { @@ -61,7 +67,9 @@ export const TemplateListPage = (props: TemplateListPageProps) => { pageTitleOverride="Create a new component" title="Create a new component" subtitle="Create new software components using standard templates in your organization" - /> + > + +
  • []; @@ -43,12 +48,12 @@ export type TemplateWizardPageProps = { export const TemplateWizardPage = (props: TemplateWizardPageProps) => { const rootRef = useRouteRef(nextRouteRef); - const taskRoute = useRouteRef(scaffolderTaskRouteRef); + const taskRoute = useRouteRef(nextScaffolderTaskRouteRef); const { secrets } = useTemplateSecrets(); const scaffolderApi = useApi(scaffolderApiRef); const navigate = useNavigate(); const { templateName, namespace } = useRouteRefParams( - selectedTemplateRouteRef, + nextSelectedTemplateRouteRef, ); const templateRef = stringifyEntityRef({ diff --git a/plugins/scaffolder/src/next/routes.ts b/plugins/scaffolder/src/next/routes.ts index 620122ee60..12fad4210a 100644 --- a/plugins/scaffolder/src/next/routes.ts +++ b/plugins/scaffolder/src/next/routes.ts @@ -34,3 +34,24 @@ export const nextScaffolderTaskRouteRef = createSubRouteRef({ parent: nextRouteRef, path: '/tasks/:taskId', }); + +/** @alpha */ +export const nextScaffolderListTaskRouteRef = createSubRouteRef({ + id: 'scaffolder/next/list-tasks', + parent: nextRouteRef, + path: '/tasks', +}); + +/** @alpha */ +export const nextActionsRouteRef = createSubRouteRef({ + id: 'scaffolder/next/actions', + parent: nextRouteRef, + path: '/actions', +}); + +/** @alpha */ +export const nextEditRouteRef = createSubRouteRef({ + id: 'scaffolder/next/edit', + parent: nextRouteRef, + path: '/edit', +}); diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 5b3f82a37b..71dccfef4f 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/api-report.md b/plugins/search-backend-module-elasticsearch/api-report.md index 9e3ca40ec7..8545e3fd8f 100644 --- a/plugins/search-backend-module-elasticsearch/api-report.md +++ b/plugins/search-backend-module-elasticsearch/api-report.md @@ -67,6 +67,11 @@ export interface BaseElasticSearchClientOptions { Transport?: ElasticSearchTransportConstructor; } +// @public (undocumented) +export function decodeElasticSearchPageCursor(pageCursor?: string): { + page: number; +}; + // @public (undocumented) export interface ElasticSearchAgentOptions { // (undocumented) diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 856f9b5e55..2eb85f5f2c 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": "1.1.3-next.0", + "version": "1.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 9edad973de..c2f4224db3 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -408,6 +408,9 @@ export class ElasticSearchSearchEngine implements SearchEngine { } } +/** + * @public + */ export function decodePageCursor(pageCursor?: string): { page: number } { if (!pageCursor) { return { page: 0 }; diff --git a/plugins/search-backend-module-elasticsearch/src/engines/index.ts b/plugins/search-backend-module-elasticsearch/src/engines/index.ts index 8c3b9e3c6d..cb24bdc56a 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/index.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export { ElasticSearchSearchEngine } from './ElasticSearchSearchEngine'; +export { + decodePageCursor as decodeElasticSearchPageCursor, + ElasticSearchSearchEngine, +} from './ElasticSearchSearchEngine'; export { isOpenSearchCompatible } from './ElasticSearchClientOptions'; export type { BaseElasticSearchClientOptions, diff --git a/plugins/search-backend-module-elasticsearch/src/index.ts b/plugins/search-backend-module-elasticsearch/src/index.ts index cb4f62098a..e0b05014cc 100644 --- a/plugins/search-backend-module-elasticsearch/src/index.ts +++ b/plugins/search-backend-module-elasticsearch/src/index.ts @@ -20,7 +20,11 @@ * @packageDocumentation */ -export { ElasticSearchSearchEngine, isOpenSearchCompatible } from './engines'; +export { + decodeElasticSearchPageCursor, + ElasticSearchSearchEngine, + isOpenSearchCompatible, +} from './engines'; export type { BaseElasticSearchClientOptions, ElasticSearchAgentOptions, diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 09082b4cd3..1d17c6707c 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.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + ## 0.5.3-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index 832a5528f9..7883475f34 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.5.3-next.0", + "version": "0.5.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 57ec19a2c4..bf9306cb1d 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-search-backend-node +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + +## 1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.1.3-next.0 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 18496a1c39..1bf73971d1 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": "1.1.3-next.0", + "version": "1.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 0dcdec3ed5..c31930c867 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-search-backend +## 1.2.3-next.2 + +### Patch Changes + +- 1b30c9a0f7: Change the router's response to include the error message instead of its object type in case it fails during a search query because the messages have more info. +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/plugin-permission-node@0.7.5-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-backend-node@1.1.3-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 1.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-permission-node@0.7.5-next.1 + - @backstage/plugin-search-backend-node@1.1.3-next.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.2.3-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 72cfadf821..31594bc8af 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": "1.2.3-next.0", + "version": "1.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index 1dbd145bce..b4772dd62d 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -74,6 +74,23 @@ describe('createRouter', () => { }); describe('GET /query', () => { + it('throws meaningful query errors', async () => { + const error = new Error('Query error message'); + mockSearchEngine.query.mockRejectedValueOnce(error); + + const response = await request(app).get('/query'); + + expect(response.status).toEqual(500); + expect(response.body).toMatchObject( + expect.objectContaining({ + error: { + name: 'Error', + message: `There was a problem performing the search query: ${error.message}`, + }, + }), + ); + }); + it('returns empty results array', async () => { const response = await request(app).get('/query'); diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index b51dcead14..10f47d180f 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -184,7 +184,7 @@ export async function createRouter( } throw new Error( - `There was a problem performing the search query. ${error}`, + `There was a problem performing the search query: ${error.message}`, ); } }, diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 37214bdb82..fa58979796 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-search-react +## 1.5.0-next.1 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + +## 1.5.0-next.0 + +### Minor Changes + +- 0eaa579f89: - Create the search results extensions, for more details see the documentation [here](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions); + - Update the `SearchResult`, `SearchResultList` and `SearchResultGroup` components to use extensions and default their props to optionally accept a query, when the query is not passed, the component tries to get it from the search context. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.4.0 ### Minor Changes diff --git a/plugins/search-react/api-report.md b/plugins/search-react/api-report.md index ccf7a72e33..375af20d5c 100644 --- a/plugins/search-react/api-report.md +++ b/plugins/search-react/api-report.md @@ -14,6 +14,7 @@ import { InputBaseProps } from '@material-ui/core'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; import { LinkProps } from '@backstage/core-components'; +import { ListItemProps } from '@material-ui/core'; import { ListItemTextProps } from '@material-ui/core'; import { ListProps } from '@material-ui/core'; import { PropsWithChildren } from 'react'; @@ -55,6 +56,7 @@ export type DefaultResultListItemProps = { highlight?: ResultHighlight; rank?: number; lineClamp?: number; + toggleModal?: () => void; }; // @public (undocumented) @@ -391,6 +393,16 @@ export type SearchResultListItemExtensionOptions< predicate?: (result: SearchResult_2) => boolean; }; +// @public +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; + // @public export const SearchResultListItemExtensions: ( props: SearchResultListItemExtensionsProps, diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index e69ec2e7ae..d353189add 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.4.0", + "version": "1.5.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx index e94d394639..aab105df48 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.test.tsx @@ -35,9 +35,10 @@ describe('DefaultResultListItem', () => { it('Includes primary/secondary text (title / text)', async () => { await renderInTestApp(); - expect(screen.getByRole('listitem')).toHaveTextContent( - result.title + result.text, - ); + expect( + screen.getByRole('link', { name: result.title }), + ).toBeInTheDocument(); + expect(screen.getByText(result.text)).toBeInTheDocument(); }); it('should render icon if prop is specified', async () => { diff --git a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx index 6ea5e4d1a2..cf89b6a9cd 100644 --- a/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx +++ b/plugins/search-react/src/components/DefaultResultListItem/DefaultResultListItem.tsx @@ -21,13 +21,7 @@ import { SearchDocument, } from '@backstage/plugin-search-common'; import { HighlightedSearchResultText } from '../HighlightedSearchResultText'; -import { - ListItem, - ListItemIcon, - ListItemText, - Box, - Divider, -} from '@material-ui/core'; +import { ListItemIcon, ListItemText, Box } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; @@ -43,6 +37,7 @@ export type DefaultResultListItemProps = { highlight?: ResultHighlight; rank?: number; lineClamp?: number; + toggleModal?: () => void; }; /** @@ -61,48 +56,45 @@ export const DefaultResultListItemComponent = ({ return ( <> - - {icon && {icon}} - - {highlight?.fields.title ? ( - - ) : ( - result.title - )} - - } - secondary={ - - {highlight?.fields.text ? ( - - ) : ( - result.text - )} - - } - /> - {secondaryAction && {secondaryAction}} - - + {icon && {icon}} + + {highlight?.fields.title ? ( + + ) : ( + result.title + )} + + } + secondary={ + + {highlight?.fields.text ? ( + + ) : ( + result.text + )} + + } + /> + {secondaryAction && {secondaryAction}} ); }; diff --git a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx index 6a5a683295..4b8caa2780 100644 --- a/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx +++ b/plugins/search-react/src/components/SearchResult/SearchResult.test.tsx @@ -16,8 +16,6 @@ import React from 'react'; import { waitFor } from '@testing-library/react'; - -import { ListItem } from '@material-ui/core'; import { wrapInTestApp, renderInTestApp, @@ -217,8 +215,7 @@ describe('SearchResult', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx index 728bd9113a..8a9e8986b8 100644 --- a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx +++ b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { ListItem, MenuItem } from '@material-ui/core'; +import { MenuItem } from '@material-ui/core'; import DocsIcon from '@material-ui/icons/InsertDriveFile'; import { @@ -143,8 +143,7 @@ describe('SearchResultGroup', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultGroupItemExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx index 7e8aa7bb33..a0f5bc7830 100644 --- a/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx +++ b/plugins/search-react/src/components/SearchResultList/SearchResultList.test.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { screen, waitFor } from '@testing-library/react'; -import { ListItem } from '@material-ui/core'; import { TestApiProvider, renderWithEffects, @@ -226,8 +225,7 @@ describe('SearchResultList', () => { }).provide( createSearchResultListItemExtension({ name: 'SearchResultListItemExtension', - component: async () => props => - Result: {props.result?.title}, + component: async () => props => <>Result: {props.result?.title}, }), ); diff --git a/plugins/search-react/src/extensions.test.tsx b/plugins/search-react/src/extensions.test.tsx index 24c115e572..7e5070c738 100644 --- a/plugins/search-react/src/extensions.test.tsx +++ b/plugins/search-react/src/extensions.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { ListItem, ListItemText } from '@material-ui/core'; +import { ListItemText } from '@material-ui/core'; import { wrapInTestApp, @@ -75,9 +75,9 @@ const createExtension = ( predicate, component = async () => (props: { result?: SearchDocument }) => ( - + <> - + ), } = options; return plugin.provide( @@ -120,7 +120,7 @@ describe('extensions', () => { ); await userEvent.click( - screen.getByRole('button', { name: /Search Result 1/ }), + screen.getByRole('link', { name: /Search Result 1/ }), ); expect(analyticsApiMock.getEvents()[0]).toMatchObject({ @@ -146,9 +146,7 @@ describe('extensions', () => { expect(screen.getByText('Default')).toBeInTheDocument(); expect(screen.getByText('Search Result 1')).toBeInTheDocument(); - await userEvent.click( - screen.getByRole('button', { name: /Search Result 1/ }), - ); + await userEvent.click(screen.getByRole('listitem')); expect(analyticsApiMock.getEvents()[0]).toMatchObject({ action: 'discover', @@ -184,9 +182,9 @@ describe('extensions', () => { predicate: (result: SearchResult) => result.type === 'explore', component: async () => (props: { result?: SearchDocument }) => ( - + <> - + ), }); diff --git a/plugins/search-react/src/extensions.tsx b/plugins/search-react/src/extensions.tsx index 1e0619b14c..6c854e24e0 100644 --- a/plugins/search-react/src/extensions.tsx +++ b/plugins/search-react/src/extensions.tsx @@ -33,7 +33,7 @@ import { } from '@backstage/core-plugin-api'; import { SearchDocument, SearchResult } from '@backstage/plugin-search-common'; -import { Box, List, ListProps } from '@material-ui/core'; +import { ListItem, List, ListProps, ListItemProps } from '@material-ui/core'; import { DefaultResultListItem } from './components'; @@ -73,26 +73,34 @@ const findSearchResultListItemExtensionElement = ( }; /** - * @internal - * Props for {@link SearchResultListItemExtension}. + * @public + * Extends props for any search result list item extension */ -type SearchResultListItemExtensionProps = PropsWithChildren<{ - rank?: number; - result?: SearchDocument; - noTrack?: boolean; -}>; +export type SearchResultListItemExtensionProps = Props & + PropsWithChildren< + { + rank?: number; + result?: SearchDocument; + noTrack?: boolean; + } & Omit + >; /** * @internal * Extends children with extension capabilities. * @param props - see {@link SearchResultListItemExtensionProps}. */ -const SearchResultListItemExtension = ({ - rank, - result, - noTrack, - children, -}: SearchResultListItemExtensionProps) => { +const SearchResultListItemExtension = ( + props: SearchResultListItemExtensionProps, +) => { + const { + rank, + result, + noTrack, + children, + alignItems = 'flex-start', + ...rest + } = props; const analytics = useAnalytics(); const handleClickCapture = useCallback(() => { @@ -105,9 +113,14 @@ const SearchResultListItemExtension = ({ }, [rank, result, noTrack, analytics]); return ( - + {children} - + ); }; diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 32eebe7fae..7853a44abb 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-search +## 1.1.0-next.2 + +### Patch Changes + +- 66e2aab4c4: Updated colors for each tab used on search modal, to improve color contrast. Aria label added to tabs wrapper component. `disableRipple` property on the `Tab` component removed to improve keyboard navigation indicator. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 1.1.0-next.1 + +### Minor Changes + +- 0eaa579f89: Update `SearchModal` component to use `SearchResult` extensions. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/version-bridge@1.0.3 + - @backstage/plugin-search-common@1.2.1 + ## 1.0.8-next.0 ### Patch Changes diff --git a/plugins/search/api-report.md b/plugins/search/api-report.md index cdbdc4c095..09c12cd776 100644 --- a/plugins/search/api-report.md +++ b/plugins/search/api-report.md @@ -97,6 +97,7 @@ export type SearchTypeAccordionProps = { icon: JSX.Element; }>; defaultValue?: string; + showCounts?: boolean; }; // @public diff --git a/plugins/search/package.json b/plugins/search/package.json index 7aa8b5a123..c2f635f762 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": "1.0.8-next.0", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx index d17cf0f6ba..c9621c5940 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.tsx @@ -42,7 +42,7 @@ import { rootRouteRef } from '../../plugin'; /** * @public - **/ + */ export interface SearchModalChildrenProps { /** * A function that should be invoked when navigating away from the modal. @@ -52,7 +52,7 @@ export interface SearchModalChildrenProps { /** * @public - **/ + */ export interface SearchModalProps { /** * If true, it renders the modal. diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx index da1cae46b9..e0acee025a 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, render } from '@testing-library/react'; +import { act, render, waitFor } from '@testing-library/react'; import user from '@testing-library/user-event'; import { searchApiRef, @@ -34,6 +34,8 @@ jest.mock('@backstage/plugin-search-react', () => ({ setTypes: (types: any) => setTypesMock(types), pageCursor: '', setPageCursor: (pageCursor: any) => setPageCursorMock(pageCursor), + term: 'abc', + filters: { foo: 'bar' }, }), })); @@ -48,7 +50,7 @@ describe('SearchType.Accordion', () => { }; beforeEach(() => { - query.mockResolvedValue({ results: [] }); + query.mockResolvedValue({ results: [], numberOfResults: 1234 }); }); const Wrapper = ({ children }: { children: React.ReactNode }) => { @@ -132,4 +134,34 @@ describe('SearchType.Accordion', () => { expect(queryByText('Collapse')).not.toBeInTheDocument(); }); + + it('should show result counts if enabled', async () => { + const { getAllByText } = render( + + + , + ); + + expect(query).toHaveBeenCalledWith({ + term: 'abc', + types: [], + filters: { foo: 'bar' }, + pageLimit: 0, + }); + expect(query).toHaveBeenCalledWith({ + term: 'abc', + types: [expectedType.value], + filters: {}, + pageLimit: 0, + }); + await waitFor(() => { + const countLabels = getAllByText('1234 results'); + expect(countLabels.length).toEqual(2); + expect(countLabels[0]).toBeInTheDocument(); + }); + }); }); diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx index 49f5cf74ca..67785b89cb 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx @@ -15,7 +15,8 @@ */ import React, { cloneElement, Fragment, useEffect, useState } from 'react'; -import { useSearch } from '@backstage/plugin-search-react'; +import { useApi } from '@backstage/core-plugin-api'; +import { searchApiRef, useSearch } from '@backstage/plugin-search-react'; import { Accordion, AccordionSummary, @@ -32,6 +33,7 @@ import { } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import AllIcon from '@material-ui/icons/FontDownload'; +import useAsync from 'react-use/lib/useAsync'; const useStyles = makeStyles(theme => ({ card: { @@ -81,13 +83,15 @@ export type SearchTypeAccordionProps = { icon: JSX.Element; }>; defaultValue?: string; + showCounts?: boolean; }; export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { const classes = useStyles(); - const { setPageCursor, setTypes, types } = useSearch(); + const { filters, setPageCursor, setTypes, term, types } = useSearch(); + const searchApi = useApi(searchApiRef); const [expanded, setExpanded] = useState(true); - const { defaultValue, name, types: givenTypes } = props; + const { defaultValue, name, showCounts, types: givenTypes } = props; const toggleExpanded = () => setExpanded(prevState => !prevState); const handleClick = (type: string) => { @@ -116,6 +120,37 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { ]; const selected = types[0] || ''; + const { value: resultCounts } = useAsync(async () => { + if (!showCounts) { + return {}; + } + + const counts = await Promise.all( + definedTypes + .map(t => t.value) + .map(async type => { + const { numberOfResults } = await searchApi.query({ + term, + types: type ? [type] : [], + filters: + types.includes(type) || (!types.length && !type) ? filters : {}, + pageLimit: 0, + }); + + return [ + type, + numberOfResults !== undefined + ? `${ + numberOfResults >= 10000 ? `>10000` : numberOfResults + } results` + : ' -- ', + ]; + }), + ); + + return Object.fromEntries(counts); + }, [filters, showCounts, term, types]); + return ( @@ -161,7 +196,10 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { className: classes.listItemIcon, })} - + ))} diff --git a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx index fc0380e23a..57a311b00c 100644 --- a/plugins/search/src/components/SearchType/SearchType.Tabs.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Tabs.tsx @@ -22,13 +22,12 @@ import { makeStyles, Tab, Tabs } from '@material-ui/core'; const useStyles = makeStyles((theme: BackstageTheme) => ({ tabs: { borderBottom: `1px solid ${theme.palette.textVerySubtle}`, - padding: theme.spacing(0, 4), }, tab: { height: '50px', fontWeight: theme.typography.fontWeightBold, fontSize: theme.typography.pxToRem(13), - color: theme.palette.textSubtle, + color: theme.palette.text.primary, minWidth: '130px', }, })); @@ -72,6 +71,7 @@ export const SearchTypeTabs = (props: SearchTypeTabsProps) => { return ( { diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 49be1fc880..922b06c8d8 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-sentry +## 0.5.0-next.2 + +### Minor Changes + +- 6a8d6b9a0c: Add option to filter issues based on the time it was triggered + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.4.8-next.1 + +### Patch Changes + +- 85b04f659a: Internal refactor to not use deprecated `substr` +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.4.8-next.0 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 72e9fbdc50..e757ff25a4 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.4.8-next.0", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx index 647208f141..5bf6b1e92b 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.test.tsx @@ -19,6 +19,7 @@ import SentryIssuesTable from './SentryIssuesTable'; import { SentryIssue } from '../../api'; import mockIssue from '../../api/mock/sentry-issue-mock.json'; import { renderInTestApp } from '@backstage/test-utils'; +import { DateTime } from 'luxon'; describe('SentryIssuesTable', () => { it('should render headers in a table', async () => { @@ -62,6 +63,7 @@ describe('SentryIssuesTable', () => { }, count: '101', userCount: 202, + lastSeen: DateTime.now().toISO(), }, ]; const table = await renderInTestApp( @@ -105,6 +107,6 @@ describe('SentryIssuesTable', () => { }} />, ); - expect(await table.findByText('Last 24h')).toBeInTheDocument(); + expect(await table.findByText('Stats for 24h')).toBeInTheDocument(); }); }); diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx index abe29efd7f..60ee6b7dbf 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx @@ -14,13 +14,19 @@ * limitations under the License. */ -import React from 'react'; +import React, { useCallback, useState } from 'react'; import { SentryIssue } from '../../api'; -import { DateTime } from 'luxon'; +import { DateTime, Duration } from 'luxon'; import { ErrorCell } from '../ErrorCell/ErrorCell'; import { ErrorGraph } from '../ErrorGraph/ErrorGraph'; import { Table, TableColumn } from '@backstage/core-components'; +import Select from '@material-ui/core/Select'; import { Options } from '@material-table/core'; +import { FormControl, Grid, MenuItem } from '@material-ui/core'; + +const ONE_DAY_IN_MILLIS = 86400000; +const SEVEN_DAYS_IN_MILLIS = ONE_DAY_IN_MILLIS * 7; +const FOURTEEN_DAYS_IN_MILLIS = ONE_DAY_IN_MILLIS * 14; const columns: TableColumn[] = [ { @@ -66,14 +72,55 @@ type SentryIssuesTableProps = { const SentryIssuesTable = (props: SentryIssuesTableProps) => { const { sentryIssues, statsFor, tableOptions } = props; + const [selected, setSelected] = useState(ONE_DAY_IN_MILLIS); + + const filterByDate = useCallback((issue, selectedFilter) => { + return ( + DateTime.fromISO(issue.lastSeen) > + DateTime.now().minus(Duration.fromMillis(selectedFilter)) + ); + }, []); + const [filteredIssues, setFilteredIssues] = useState( + sentryIssues.filter(i => filterByDate(i, selected)), + ); + + const handleFilterChange = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + ) => { + const item = event.target.value; + if (typeof item === 'number') { + setSelected(item); + if (item === Number.NEGATIVE_INFINITY) { + setFilteredIssues(sentryIssues); + return; + } + setFilteredIssues(sentryIssues.filter(i => filterByDate(i, item))); + } + }; return ( - + <> +
    + Sentry Issues + + + + + + + } + subtitle={statsFor ? `Stats for ${statsFor}` : undefined} + data={filteredIssues} + /> + ); }; diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index f301ff2692..94baec18aa 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-shortcuts +## 0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + +## 0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.3.6 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 22e5abe6ad..61b48b1c55 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.3.6", + "version": "0.3.7-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 0475073584..6fb7414acb 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-sonarqube-backend +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.7-next.0 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 5aa8367434..99c0a8b486 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.1.7-next.0", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 41b5d5b371..b938ce8b37 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-sonarqube-react +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-plugin-api@1.3.0 + ## 0.1.2-next.0 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index ebf75572ec..53837a47cf 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.2-next.0", + "version": "0.1.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 0d71fd4f9a..e51e0a65ac 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-sonarqube +## 0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-sonarqube-react@0.1.2-next.1 + +## 0.6.3-next.1 + +### Patch Changes + +- 6310eacc11: Additional export added in order to bind SonarQubeClient to its apiref +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-sonarqube-react@0.1.2-next.0 + ## 0.6.3-next.0 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index ae37737b94..80dd578523 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.6.3-next.0", + "version": "0.6.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index e92f250fad..c5de65a3d3 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-splunk-on-call +## 0.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.4.4-next.0 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 8e2b7f278c..097cc1c6fd 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.4.4-next.0", + "version": "0.4.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts b/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts index 764ac94e2c..9beb4e150e 100644 --- a/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts +++ b/plugins/splunk-on-call/src/components/TriggerDialog/testUtils.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// eslint-disable-next-line import/no-extraneous-dependencies +// eslint-disable-next-line @backstage/no-undeclared-imports import { act, fireEvent, diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 7a2535eae5..aac07808c9 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 4d5009bee1..e40e3e846a 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.11-next.0", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index e9ad1d9958..f80e350a03 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-stack-overflow +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-home@0.4.31-next.2 + - @backstage/plugin-search-common@1.2.1 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-home@0.4.31-next.1 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-common@1.2.1 + ## 0.1.11-next.0 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 62a15a30c1..c9fbe7e7a3 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.11-next.0", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/src/api/StackOverflowClient.ts b/plugins/stack-overflow/src/api/StackOverflowClient.ts index f4ff5bf190..f598f912bd 100644 --- a/plugins/stack-overflow/src/api/StackOverflowClient.ts +++ b/plugins/stack-overflow/src/api/StackOverflowClient.ts @@ -39,9 +39,8 @@ export class StackOverflowClient implements StackOverflowApi { } /** - * List Questions in the StackOverflow instance - * - * */ + * List questions in the StackOverflow instance + */ async listQuestions(options: { requestParams: StackOverflowQuestionsRequestParams; }): Promise { diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 96e65d116b..28a8ae4e05 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## 0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.1.26-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 1a6d87ec6f..d3a3260f87 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.26-next.0", + "version": "0.1.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 89753667a1..bef4e4c472 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-tech-insights-backend +## 0.5.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.2 + +## 0.5.8-next.1 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/plugin-tech-insights-node@0.4.0-next.1 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + ## 0.5.8-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index edb94c5784..2b32f72763 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.5.8-next.0", + "version": "0.5.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-common/CHANGELOG.md b/plugins/tech-insights-common/CHANGELOG.md index 555a77689f..347a4387d0 100644 --- a/plugins/tech-insights-common/CHANGELOG.md +++ b/plugins/tech-insights-common/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-tech-insights-common +## 0.2.10-next.0 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/types@1.0.2 + ## 0.2.9 ### Patch Changes diff --git a/plugins/tech-insights-common/package.json b/plugins/tech-insights-common/package.json index f238785e54..d7534b2834 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.9", + "version": "0.2.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index d7986767ae..aa058fdc3b 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-tech-insights-node +## 0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## 0.4.0-next.1 + +### Minor Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/config@1.0.6 + - @backstage/types@1.0.2 + ## 0.3.10-next.0 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 2981b652a5..7f49679030 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.3.10-next.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/src/facts.ts b/plugins/tech-insights-node/src/facts.ts index 3619f8b66f..b35ad756ed 100644 --- a/plugins/tech-insights-node/src/facts.ts +++ b/plugins/tech-insights-node/src/facts.ts @@ -162,7 +162,7 @@ export interface FactRetriever { * \{ timeToLive: 1209600000 \} * \{ timeToLive: \{ weeks: 4 \} \} * - **/ + */ export type TTL = { timeToLive: DurationLike }; /** @@ -172,7 +172,7 @@ export type TTL = { timeToLive: DurationLike }; * @example * \{ maxItems: 10 \} * - **/ + */ export type MaxItems = { maxItems: number }; /** diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 247c9605f4..37e46a4b5a 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-tech-insights +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + +## 0.3.7-next.1 + +### Patch Changes + +- 4024b37449: TechInsightsApi interface now has getFactSchemas() method. + TechInsightsClient now implements method getFactSchemas(). + + **BREAKING** FactSchema type moved from @backstage/plugin-tech-insights-node into @backstage/plugin-tech-insights-common + + These changes are **required** if you were importing this type directly. + + ```diff + - import { FactSchema } from '@backstage/plugin-tech-insights-node'; + + import { FactSchema } from '@backstage/plugin-tech-insights-common'; + ``` + +- Updated dependencies + - @backstage/plugin-tech-insights-common@0.2.10-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.3.7-next.0 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index fe815a044d..e874d2ba30 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.7-next.0", + "version": "0.3.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 085aa42aa9..37aa1e8336 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-tech-radar +## 0.6.1-next.1 + +### Patch Changes + +- acf6c8c10b: Deprecate `RadarEntry.url` - use `RadarEntry.links` instead + + ```diff + - url: 'https://www.javascript.com/', + key: 'javascript', + id: 'javascript', + title: 'JavaScript', + quadrant: 'languages', + links: [ + + { + + url: 'https://www.javascript.com/', + + title: 'Learn more', + + }, + ], + ``` + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + +## 0.6.1-next.0 + +### Patch Changes + +- 18024a231c: Allow to set additional links to the entry description. +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/theme@0.2.16 + ## 0.6.0 ### Minor Changes diff --git a/plugins/tech-radar/api-report.md b/plugins/tech-radar/api-report.md index e2744872d8..3b84990d85 100644 --- a/plugins/tech-radar/api-report.md +++ b/plugins/tech-radar/api-report.md @@ -25,7 +25,8 @@ export interface RadarEntry { quadrant: string; timeline: Array; title: string; - url: string; + // @deprecated + url?: string; } // @public diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index a7ce33c427..2aad00f224 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.6.0", + "version": "0.6.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts index 0fbc88255a..c0b8fb8852 100644 --- a/plugins/tech-radar/src/api.ts +++ b/plugins/tech-radar/src/api.ts @@ -133,8 +133,10 @@ export interface RadarEntry { * @remarks * * You can use `#` if you don't want to provide any other url + * + * @deprecated Use {@link RadarEntry.links} instead */ - url: string; + url?: string; /** * History of the Entry moving through {@link RadarRing} */ diff --git a/plugins/tech-radar/src/sample.ts b/plugins/tech-radar/src/sample.ts index 1c4f7a1a01..395b4f2ff5 100644 --- a/plugins/tech-radar/src/sample.ts +++ b/plugins/tech-radar/src/sample.ts @@ -45,12 +45,15 @@ entries.push({ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua', }, ], - url: 'https://www.javascript.com/', key: 'javascript', id: 'javascript', title: 'JavaScript', quadrant: 'languages', links: [ + { + url: 'https://www.javascript.com/', + title: 'Learn more', + }, { url: 'https://www.typescriptlang.org/', title: 'TypeScript', @@ -69,7 +72,6 @@ entries.push({ 'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat', }, ], - url: '#', key: 'typescript', id: 'typescript', title: 'TypeScript', @@ -87,7 +89,12 @@ entries.push({ 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur', }, ], - url: 'https://webpack.js.org/', + links: [ + { + url: 'https://webpack.js.org/', + title: 'Learn more', + }, + ], key: 'webpack', id: 'webpack', title: 'Webpack', @@ -101,7 +108,12 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: 'https://reactjs.org/', + links: [ + { + url: 'https://reactjs.org/', + title: 'Learn more', + }, + ], key: 'react', id: 'react', title: 'React', @@ -115,7 +127,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'code-reviews', id: 'code-reviews', title: 'Code Reviews', @@ -129,7 +140,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'mob-programming', id: 'mob-programming', title: 'Mob Programming', @@ -143,7 +153,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'docs-like-code', id: 'docs-like-code', title: 'Docs-like-code', @@ -156,7 +165,6 @@ entries.push({ date: new Date('2020-08-06'), }, ], - url: '#', key: 'force-push', id: 'force-push', title: 'Force push to master', @@ -170,7 +178,12 @@ entries.push({ description: 'long description', }, ], - url: 'https://github.com', + links: [ + { + url: 'https://github.com', + title: 'Learn more', + }, + ], key: 'github-actions', id: 'github-actions', title: 'GitHub Actions', diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index a27d587f36..9afcf3aace 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.2 + - @backstage/plugin-catalog@1.8.0-next.2 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## 1.0.10-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/plugin-techdocs@1.5.0-next.1 + - @backstage/plugin-catalog@1.8.0-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/test-utils@1.2.5-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + ## 1.0.10-next.0 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index baff541f54..1ad762a09d 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.10-next.0", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,7 +42,7 @@ "@backstage/plugin-techdocs-react": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@testing-library/react": "^12.1.3", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index f669d1924b..dbad0b17b1 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-techdocs-backend +## 1.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.1 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.2 + +## 1.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/plugin-catalog-common@1.0.11-next.0 + - @backstage/plugin-permission-common@0.7.3 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-node@1.4.6-next.1 + ## 1.5.3-next.0 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 396aba2fca..9c8ce22bef 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": "1.5.3-next.0", + "version": "1.5.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 09eee1fc12..b4c2d2ee26 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -186,6 +186,9 @@ export class DocsBuilder { etag: newEtag, logger: this.logger, logStream: this.logStream, + siteOptions: { + name: this.entity.metadata.title ?? this.entity.metadata.name, + }, }); // Remove Prepared directory since it is no longer needed. diff --git a/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts b/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts index 039f1db09f..fa4c81682c 100644 --- a/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts +++ b/plugins/techdocs-backend/src/cache/TechDocsCache.test.ts @@ -31,6 +31,7 @@ describe('TechDocsCache', () => { get: jest.fn(), set: jest.fn(), delete: jest.fn(), + withOptions: jest.fn(), }; CacheUnderTest = TechDocsCache.fromConfig(new ConfigReader({}), { cache: MockClient, diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts index 1445079d12..52a3b82651 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.test.ts @@ -32,6 +32,7 @@ import { DocsBuilder, shouldCheckForUpdate } from '../DocsBuilder'; import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer'; jest.mock('../DocsBuilder'); +jest.useFakeTimers(); jest.mock('node-fetch', () => ({ __esModule: true, @@ -130,6 +131,8 @@ describe('DocsSynchronizer', () => { const logger = MockedDocsBuilder.mock.calls[0][0].logger; + jest.advanceTimersByTime(10001); + logger.info('Some more log'); return true; @@ -144,13 +147,19 @@ describe('DocsSynchronizer', () => { generators, }); - expect(mockResponseHandler.log).toHaveBeenCalledTimes(3); + expect(mockResponseHandler.log).toHaveBeenCalledTimes(4); expect(mockResponseHandler.log).toHaveBeenCalledWith('Some log'); expect(mockResponseHandler.log).toHaveBeenCalledWith('Another log'); expect(mockResponseHandler.log).toHaveBeenCalledWith( expect.stringMatching(/info.*Some more log/), ); + expect(mockResponseHandler.log).toHaveBeenCalledWith( + expect.stringMatching( + /info.*The docs building process is taking a little bit longer to process this entity. Please bear with us/, + ), + ); + expect(mockResponseHandler.finish).toHaveBeenCalledWith({ updated: true, }); diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 647447a612..3d89d1647f 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -128,7 +128,13 @@ export class DocsSynchronizer { cache: this.cache, }); + const interval = setInterval(() => { + taskLogger.info( + 'The docs building process is taking a little bit longer to process this entity. Please bear with us.', + ); + }, 10000); const updated = await this.buildLimiter(() => docsBuilder.build()); + clearInterval(interval); if (!updated) { finish({ updated: false }); diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 0f0c2999bd..22630158f1 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## 1.0.10-next.1 + +### Patch Changes + +- d950d3e217: Depend on `@material-ui/core` version `^4.12.2` like all other in-repo packages +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + ## 1.0.10-next.0 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 68fad9121d..c242bb02f2 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -10,6 +10,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; // @public export const ExpandableNavigation: () => JSX.Element | null; +// @public +export const LightBox: () => JSX.Element | null; + // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index ae5d263268..c077ccdd6c 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.10-next.0", + "version": "1.0.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,11 +39,12 @@ "@backstage/integration-react": "workspace:^", "@backstage/plugin-techdocs-react": "workspace:^", "@backstage/theme": "workspace:^", - "@material-ui/core": "^4.9.13", + "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@react-hookz/web": "^20.0.0", "git-url-parse": "^13.0.0", + "photoswipe": "^5.3.5", "react-use": "^17.2.4" }, "peerDependencies": { diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx new file mode 100644 index 0000000000..b63aed8777 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.test.tsx @@ -0,0 +1,50 @@ +/* + * 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 { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils'; + +import React from 'react'; + +import { LightBox } from '../plugin'; + +describe('LightBox', () => { + it('renders without exploding', async () => { + const { getByText } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(TEST_CONTENT) + .renderWithEffects(); + + expect(getByText('TEST_CONTENT')).toBeInTheDocument(); + }); + + it('Add onclick event to images', async () => { + const { getByTestId } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom( + dog, + ) + .renderWithEffects(); + + expect(getByTestId('fixture').onclick).not.toBeUndefined(); + expect(getByTestId('fixture').onclick).toEqual(expect.any(Function)); + }); +}); diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx new file mode 100644 index 0000000000..b74c2f9659 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/LightBox.tsx @@ -0,0 +1,71 @@ +/* + * 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 { useEffect } from 'react'; +import { useShadowRootElements } from '@backstage/plugin-techdocs-react'; +// @ts-ignore +import PhotoSwipeLightbox, { DataSource } from 'photoswipe/lightbox'; +import PhotoSwipe from 'photoswipe'; +import 'photoswipe/style.css'; +import './lightbox.css'; + +export const LightBoxAddon = () => { + const images = useShadowRootElements(['img']); + + useEffect(() => { + let dataSourceImages: DataSource | null = null; + + let lightbox = new PhotoSwipeLightbox({ + pswpModule: PhotoSwipe, + wheelToZoom: true, + arrowPrevSVG: + '', + arrowNextSVG: + '', + closeSVG: + '', + zoomSVG: + '', + }); + + images.forEach((image, index) => { + image.onclick = () => { + if (dataSourceImages === null) { + dataSourceImages = images.map(dataSourceImage => { + return { + element: dataSourceImage, + src: dataSourceImage.src, + msrc: dataSourceImage.src, + alt: dataSourceImage.alt, + width: dataSourceImage.clientWidth, + height: dataSourceImage.clientHeight, + }; + }); + } + lightbox.loadAndOpen(index, dataSourceImages); + return false; + }; + }); + lightbox.init(); + + return () => { + lightbox.destroy(); + lightbox = null; + }; + }, [images]); + + return null; +}; diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts b/plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts new file mode 100644 index 0000000000..144359abb7 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/index.ts @@ -0,0 +1,16 @@ +/* + * 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 './LightBox'; diff --git a/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css new file mode 100644 index 0000000000..63170792f1 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/LigthBox/lightbox.css @@ -0,0 +1,7 @@ +.pswp { + --pswp-bg: #f8f8f8; +} +.pswp__counter { + color: rgba(0, 0, 0, 0.87); + text-shadow: none; +} diff --git a/plugins/techdocs-module-addons-contrib/src/index.ts b/plugins/techdocs-module-addons-contrib/src/index.ts index 528afe5c0d..bad7701486 100644 --- a/plugins/techdocs-module-addons-contrib/src/index.ts +++ b/plugins/techdocs-module-addons-contrib/src/index.ts @@ -25,6 +25,7 @@ export { ExpandableNavigation, ReportIssue, TextSize, + LightBox, } from './plugin'; export type { ReportIssueProps, diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index 6136f176d0..c4023a72af 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -22,6 +22,7 @@ import { import { ExpandableNavigationAddon } from './ExpandableNavigation'; import { ReportIssueAddon, ReportIssueProps } from './ReportIssue'; import { TextSizeAddon } from './TextSize'; +import { LightBoxAddon } from './LigthBox'; /** * The TechDocs addons contrib plugin @@ -203,3 +204,49 @@ export const TextSize = techdocsModuleAddonsContribPlugin.provide( component: TextSizeAddon, }), ); + +/** + * This TechDocs addon allows users to open images in a lightbox on documentation pages, they can navigate between images if there are several on one page. + * + * @remarks + * The image size of the lightbox image is the same as the image size on the document page. + * + * @example + * Here's a simple example: + * ``` + * import { + * DefaultTechDocsHome, + * TechDocsIndexPage, + * TechDocsReaderPage, + * } from '@backstage/plugin-techdocs'; + * import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; + * import { LightBox } from '@backstage/plugin-techdocs-module-addons-contrib'; + * + * + * const AppRoutes = () => { + * + * // other plugin routes + * }> + * + * + * } + * > + * + * + * + * + * ; + * }; + * ``` + * + * @public + */ +export const LightBox = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'LightBox', + location: TechDocsAddonLocations.Content, + component: LightBoxAddon, + }), +); diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 7aca6e0041..a6d32d8d9f 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-techdocs-node +## 1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + +## 1.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-aws-node@0.1.1 + - @backstage/plugin-search-common@1.2.1 + ## 1.4.6-next.0 ### Patch Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index e27b406478..ce5bd1ae09 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -54,6 +54,9 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; + siteOptions?: { + name?: string; + }; }; // @public @@ -85,6 +88,18 @@ export const getLocationForEntity: ( scmIntegration: ScmIntegrationRegistry, ) => ParsedLocationAnnotation; +// @public +export const getMkDocsYml: ( + inputDir: string, + siteOptions?: { + name?: string; + }, +) => Promise<{ + path: string; + content: string; + configIsTemporary: boolean; +}>; + // @public export type MigrateRequest = { removeOriginal?: boolean; diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index fa2587953c..0a6ffd721b 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.4.6-next.0", + "version": "1.4.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml new file mode 100644 index 0000000000..460e5c0e1d --- /dev/null +++ b/plugins/techdocs-node/src/stages/generate/__fixtures__/mkdocs_default.yml @@ -0,0 +1,4 @@ +site_name: Default Test site name +docs_dir: docs +plugins: + - techdocs-core diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index e894b0602e..e635542a7c 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -25,7 +25,7 @@ import { ParsedLocationAnnotation } from '../../helpers'; import { createOrUpdateMetadata, getGeneratorKey, - getMkdocsYml, + getMkDocsYml, getRepoUrlFromLocationAnnotation, patchIndexPreBuild, storeEtagMetadata, @@ -42,12 +42,16 @@ const mockEntity = { kind: 'TestKind', metadata: { name: 'testName', + title: 'Test site name', }, }; const mkdocsYml = fs.readFileSync( resolvePath(__filename, '../__fixtures__/mkdocs.yml'), ); +const mkdocsDefaultYml = fs.readFileSync( + resolvePath(__filename, '../__fixtures__/mkdocs_default.yml'), +); const mkdocsYmlWithExtensions = fs.readFileSync( resolvePath(__filename, '../__fixtures__/mkdocs_with_extensions.yml'), ); @@ -186,6 +190,7 @@ describe('helpers', () => { beforeEach(() => { mockFs({ '/mkdocs.yml': mkdocsYml, + '/mkdocs_default.yml': mkdocsDefaultYml, '/mkdocs_with_repo_url.yml': mkdocsYmlWithRepoUrl, '/mkdocs_with_edit_uri.yml': mkdocsYmlWithEditUri, '/mkdocs_with_extensions.yml': mkdocsYmlWithExtensions, @@ -512,30 +517,62 @@ describe('helpers', () => { }); }); - describe('getMkdocsYml', () => { + describe('getMkDocsYml', () => { const inputDir = resolvePath(__filename, '../__fixtures__/'); + const siteOptions = { + name: mockEntity.metadata.title, + }; it('returns expected contents when .yml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml(inputDir); + const { + path: mkdocsPath, + content, + configIsTemporary, + } = await getMkDocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); + expect(configIsTemporary).toBe(false); }); it('returns expected contents when .yaml file is present', async () => { const key = path.join(inputDir, 'mkdocs.yaml'); mockFs({ [key]: mkdocsYml }); - const { path: mkdocsPath, content } = await getMkdocsYml(inputDir); + const { + path: mkdocsPath, + content, + configIsTemporary, + } = await getMkDocsYml(inputDir, siteOptions); expect(mkdocsPath).toBe(key); expect(content).toBe(mkdocsYml.toString()); + expect(configIsTemporary).toBe(false); }); - it('throws when neither .yml nor .yaml file is present', async () => { + it('returns expected contents when default file is present', async () => { + const defaultSiteOptions = { + name: 'Default Test site name', + }; + const key = path.join(inputDir, 'mkdocs.yml'); + const mockPathExists = jest.spyOn(fs, 'pathExists'); + mockPathExists.mockImplementation(() => Promise.resolve(false)); + mockFs({ [key]: mkdocsDefaultYml }); + const { + path: mkdocsPath, + content, + configIsTemporary, + } = await getMkDocsYml(inputDir, defaultSiteOptions); + + expect(mkdocsPath).toBe(key); + expect(content).toBe(mkdocsDefaultYml.toString()); + expect(configIsTemporary).toBe(true); + }); + + it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkdocsYml(invalidInputDir)).rejects.toThrow( - /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation/, + await expect(getMkDocsYml(invalidInputDir, siteOptions)).rejects.toThrow( + /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); }); diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index 50db0eb86a..27c24ea66e 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -26,7 +26,7 @@ import path, { resolve as resolvePath } from 'path'; import { PassThrough, Writable } from 'stream'; import { Logger } from 'winston'; import { ParsedLocationAnnotation } from '../../helpers'; -import { SupportedGeneratorKey } from './types'; +import { DefaultMkdocsContent, SupportedGeneratorKey } from './types'; import { getFileTreeRecursively } from '../publish/helpers'; // TODO: Implement proper support for more generators. @@ -150,36 +150,90 @@ export const MKDOCS_SCHEMA = DEFAULT_SCHEMA.extend([ }), ]); +/** + * Generates a mkdocs.yml configuration file + * + * @param inputDir - base dir to where the mkdocs.yml file will be created + * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the + * required `site_name` property, default value is "Documentation Site" + */ +export const generateMkdocsYml = async ( + inputDir: string, + siteOptions?: { name?: string }, +) => { + try { + // TODO(awanlin): Use a provided default mkdocs.yml + // from config or some specified location. If this is + // not provided then fall back to generating bare + // minimum mkdocs.yml file + + const mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + const defaultSiteName = siteOptions?.name ?? 'Documentation Site'; + const defaultMkdocsContent: DefaultMkdocsContent = { + site_name: defaultSiteName, + docs_dir: 'docs', + plugins: ['techdocs-core'], + }; + + await fs.writeFile( + mkdocsYmlPath, + yaml.dump(defaultMkdocsContent, { schema: MKDOCS_SCHEMA }), + ); + } catch (error) { + throw new ForwardedError('Could not generate mkdocs.yml file', error); + } +}; + /** * Finds and loads the contents of either an mkdocs.yml or mkdocs.yaml file, * depending on which is present (MkDocs supports both as of v1.2.2). + * @public * - * @param inputDir - base dir to be searched for either an mkdocs.yml or - * mkdocs.yaml file. + * @param inputDir - base dir to be searched for either an mkdocs.yml or mkdocs.yaml file. + * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the + * required `site_name` property, default value is "Documentation Site" */ -export const getMkdocsYml = async ( +export const getMkDocsYml = async ( inputDir: string, -): Promise<{ path: string; content: string }> => { + siteOptions?: { name?: string }, +): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; try { mkdocsYmlPath = path.join(inputDir, 'mkdocs.yaml'); - mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); - } catch { - try { - mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + if (await fs.pathExists(mkdocsYmlPath)) { mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); - } catch (error) { - throw new ForwardedError( - 'Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml for validation', - error, - ); + return { + path: mkdocsYmlPath, + content: mkdocsYmlFileString, + configIsTemporary: false, + }; } + + mkdocsYmlPath = path.join(inputDir, 'mkdocs.yml'); + if (await fs.pathExists(mkdocsYmlPath)) { + mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); + return { + path: mkdocsYmlPath, + content: mkdocsYmlFileString, + configIsTemporary: false, + }; + } + + // No mkdocs file, generate it + await generateMkdocsYml(inputDir, siteOptions); + mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); + } catch (error) { + throw new ForwardedError( + 'Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation', + error, + ); } return { path: mkdocsYmlPath, content: mkdocsYmlFileString, + configIsTemporary: true, }; }; diff --git a/plugins/techdocs-node/src/stages/generate/index.ts b/plugins/techdocs-node/src/stages/generate/index.ts index 1c20c58887..fa36486a0f 100644 --- a/plugins/techdocs-node/src/stages/generate/index.ts +++ b/plugins/techdocs-node/src/stages/generate/index.ts @@ -15,6 +15,7 @@ */ export { TechdocsGenerator } from './techdocs'; export { Generators } from './generators'; +export { getMkDocsYml } from './helpers'; export type { GeneratorBase, GeneratorOptions, diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index 9bbc58ebdc..93285b7468 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -24,7 +24,7 @@ import { } from '@backstage/integration'; import { createOrUpdateMetadata, - getMkdocsYml, + getMkDocsYml, patchIndexPreBuild, runCommand, storeEtagMetadata, @@ -96,10 +96,14 @@ export class TechdocsGenerator implements GeneratorBase { etag, logger: childLogger, logStream, + siteOptions, } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url - const { path: mkdocsYmlPath, content } = await getMkdocsYml(inputDir); + const { path: mkdocsYmlPath, content } = await getMkDocsYml( + inputDir, + siteOptions, + ); // validate the docs_dir first const docsDir = await validateMkdocsYaml(inputDir, content); diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index 2b2bbb21c9..70c332344a 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -53,6 +53,7 @@ export type GeneratorConfig = { * @param etag - A unique identifier for the prepared tree e.g. commit SHA. If provided it will be stored in techdocs_metadata.json. * @param logger - A logger that forwards the messages to the caller to be displayed outside of the backend. * @param logStream - A log stream that can send raw log messages to the caller to be displayed outside of the backend. + * @param siteOptions - Options for the site: The `name` property will be used in mkdocs.yml config for the required `site_name` property, default value is "Documentation Site" */ export type GeneratorRunOptions = { inputDir: string; @@ -61,6 +62,7 @@ export type GeneratorRunOptions = { etag?: string; logger: Logger; logStream?: Writable; + siteOptions?: { name?: string }; }; /** @@ -89,3 +91,9 @@ export type GeneratorBuilder = { register(protocol: SupportedGeneratorKey, generator: GeneratorBase): void; get(entity: Entity): GeneratorBase; }; + +export type DefaultMkdocsContent = { + site_name: string; + docs_dir: string; + plugins: String[]; +}; diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 4f9744158d..34617eb3f5 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-techdocs-react +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + +## 1.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/version-bridge@1.0.3 + ## 1.1.3-next.0 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 781ba74c94..29587c3e1e 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.3-next.0", + "version": "1.1.3-next.2", "publishConfig": { "access": "public", "alphaTypes": "dist/index.alpha.d.ts", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 22d52c02e8..352114d77d 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-techdocs +## 1.5.0-next.2 + +### Patch Changes + +- 66e2aab4c4: `ListItem` wrapper component moved to `SearchResultListItemExtension` for all `*SearchResultListItems` that are exported as extensions. This is to make sure the list only contains list elements. + + Note: If you have implemented a custom result list item, we recommend you to remove the list item wrapper to avoid nested `
  • ` elements. + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-search-react@1.5.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.1 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.2 + +## 1.5.0-next.1 + +### Minor Changes + +- 20840b36b4: Update DocsTable and EntityListDocsTable to accept overrides for Material Table options. +- 0eaa579f89: The `TechDocsSearchResultListItem` component is now a search result extension. This means that when rendered as a child of components that render search extensions, the `result`, `rank`, and `highlight` properties are optional. See the [documentation](https://backstage.io/docs/features/search/how-to-guides#how-to-render-search-results-using-extensions) for more details. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-search-react@1.5.0-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + - @backstage/integration-react@1.1.10-next.0 + - @backstage/theme@0.2.16 + - @backstage/plugin-search-common@1.2.1 + - @backstage/plugin-techdocs-react@1.1.3-next.1 + ## 1.4.4-next.0 ### Patch Changes diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index ddc90d07bb..9452b38feb 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -19,6 +19,7 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; import { TableColumn } from '@backstage/core-components'; import { TableOptions } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; @@ -400,7 +401,7 @@ export type TechDocsSearchProps = { // @public export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null; // @public diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index d04115188b..5e113f3e7f 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": "1.4.4-next.0", + "version": "1.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 331eefe121..bdd4814898 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -33,7 +33,10 @@ import { fetchApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { createSearchResultListItemExtension } from '@backstage/plugin-search-react'; +import { + createSearchResultListItemExtension, + SearchResultListItemExtensionProps, +} from '@backstage/plugin-search-react'; import { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem'; /** @@ -162,7 +165,7 @@ export const TechDocsReaderPage = techdocsPlugin.provide( * @public */ export const TechDocsSearchResultListItem: ( - props: TechDocsSearchResultListItemProps, + props: SearchResultListItemExtensionProps, ) => JSX.Element | null = techdocsPlugin.provide( createSearchResultListItemExtension({ name: 'TechDocsSearchResultListItem', diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx index ffe95e0b7e..ea7e4ed77b 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx @@ -102,6 +102,7 @@ CONFIGURATION 4: and provided content in + diff --git a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx index f058fd0a9e..9bf8b76092 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx @@ -15,13 +15,7 @@ */ import React, { PropsWithChildren, ReactNode } from 'react'; -import { - Divider, - ListItem, - ListItemIcon, - ListItemText, - makeStyles, -} from '@material-ui/core'; +import { ListItemIcon, ListItemText, makeStyles } from '@material-ui/core'; import Typography from '@material-ui/core/Typography'; import { Link } from '@backstage/core-components'; import { ResultHighlight } from '@backstage/plugin-search-common'; @@ -157,11 +151,8 @@ export const TechDocsSearchResultListItem = ( const ListItemWrapper = ({ children }: PropsWithChildren<{}>) => asListItem ? ( <> - - {icon && {icon}} -
    {children}
    -
    - + {icon && {icon}} +
    {children}
    ) : ( <>{children} diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index ae9ec851f0..9f44d33d18 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-todo-backend +## 0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/catalog-client@1.3.1-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + +## 0.1.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-client@1.3.1-next.0 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + - @backstage/integration@1.4.2 + ## 0.1.39-next.0 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 3fbc52bb70..6120e76a5e 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.39-next.0", + "version": "0.1.39-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index fa5fb5064b..49a8241e30 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-todo +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.17-next.0 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 00ea5873d6..d337834872 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.17-next.0", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 90069ca40c..20a7f0c6e5 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-user-settings-backend +## 0.1.6-next.2 + +### Patch Changes + +- 0ff03319be: Updated usage of `createBackendPlugin`. +- 4a6f38a535: Added a Backend System plugin feature +- Updated dependencies + - @backstage/backend-plugin-api@0.4.0-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.11-next.2 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + +## 0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/errors@1.1.4 + - @backstage/types@1.0.2 + - @backstage/plugin-auth-node@0.2.11-next.1 + ## 0.1.6-next.0 ### Patch Changes diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 1bc37bbec7..b015915723 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-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 { BackendFeature } from '@backstage/backend-plugin-api'; import express from 'express'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; @@ -18,5 +19,8 @@ export interface RouterOptions { identity: IdentityApi; } +// @alpha +export const userSettingsPlugin: () => BackendFeature; + // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index f69f13bcee..b77050a5af 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.1.6-next.0", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -11,7 +11,8 @@ "publishConfig": { "access": "public", "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" }, "repository": { "type": "git", @@ -20,7 +21,7 @@ }, "scripts": { "start": "backstage-cli package start", - "build": "backstage-cli package build", + "build": "backstage-cli package build --experimental-type-build", "lint": "backstage-cli package lint", "test": "backstage-cli package test", "prepack": "backstage-cli package prepack", @@ -29,6 +30,7 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", @@ -48,6 +50,7 @@ }, "files": [ "dist", - "migrations" + "migrations", + "alpha" ] } diff --git a/plugins/user-settings-backend/src/index.ts b/plugins/user-settings-backend/src/index.ts index 04d8accdaf..5504aaa564 100644 --- a/plugins/user-settings-backend/src/index.ts +++ b/plugins/user-settings-backend/src/index.ts @@ -16,3 +16,4 @@ export * from './service'; export * from './database'; +export { userSettingsPlugin } from './plugin'; diff --git a/plugins/user-settings-backend/src/plugin.ts b/plugins/user-settings-backend/src/plugin.ts new file mode 100644 index 0000000000..e200d22ffe --- /dev/null +++ b/plugins/user-settings-backend/src/plugin.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2023 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 { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { createRouter } from './service/router'; + +/** + * The user settings backend plugin. + * + * @alpha + */ +export const userSettingsPlugin = createBackendPlugin({ + pluginId: 'userSettings', + register(env) { + env.registerInit({ + deps: { + database: coreServices.database, + identity: coreServices.identity, + httpRouter: coreServices.httpRouter, + }, + async init({ database, identity, httpRouter }) { + httpRouter.use(await createRouter({ database, identity })); + }, + }); + }, +}); diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index aa64c91086..478b60b6da 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-user-settings +## 0.6.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.4.1-next.0 + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/types@1.0.2 + ## 0.6.3-next.0 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 64f1cdd8d3..319ce98fee 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.6.3-next.0", + "version": "0.6.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index e81269ec17..2c7715cd73 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-vault-backend +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-test-utils@0.1.34-next.2 + - @backstage/backend-common@0.18.2-next.2 + - @backstage/backend-tasks@0.4.3-next.2 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.18.2-next.1 + - @backstage/backend-tasks@0.4.3-next.1 + - @backstage/backend-test-utils@0.1.34-next.1 + - @backstage/config@1.0.6 + - @backstage/errors@1.1.4 + ## 0.2.8-next.0 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 507c2c5713..ae7c89a61c 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.2.8-next.0", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,6 @@ "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/backend-tasks": "workspace:^", - "@backstage/backend-test-utils": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@types/express": "*", @@ -50,6 +49,7 @@ "yn": "^5.0.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/compression": "^1.7.2", "@types/supertest": "^2.0.8", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index 5ea984e2ef..60fe5c4c8b 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-vault +## 0.1.9-next.2 + +### Patch Changes + +- fd7a77b9c4: Surface additional context and details to the Backstage UI when the Vault plugin encounters non-successful HTTP responses from the Vault API. +- Updated dependencies + - @backstage/catalog-model@1.2.0-next.1 + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + - @backstage/plugin-catalog-react@1.3.0-next.2 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/plugin-catalog-react@1.3.0-next.1 + - @backstage/catalog-model@1.1.6-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 26376c18d5..15bae8c3ad 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.9-next.0", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/src/api.test.ts b/plugins/vault/src/api.test.ts index 4ce6f95c41..471cadc87e 100644 --- a/plugins/vault/src/api.test.ts +++ b/plugins/vault/src/api.test.ts @@ -50,8 +50,10 @@ describe('api', () => { const { path } = req.params; if (path === 'test/success') { return res(ctx.json(mockSecretsResult)); - } else if (path === 'test/error') { + } else if (path === 'test/empty') { return res(ctx.json({ items: [] })); + } else if (path === 'test/not-found') { + return res(ctx.status(404)); } return res(ctx.status(400)); }), @@ -72,7 +74,7 @@ describe('api', () => { it('should return empty secret list', async () => { setupHandlers(); const api = new VaultClient({ discoveryApi }); - expect(await api.listSecrets('test/error')).toEqual([]); + expect(await api.listSecrets('test/empty')).toEqual([]); }); it('should return all the secrets if no path defined', async () => { @@ -80,4 +82,20 @@ describe('api', () => { const api = new VaultClient({ discoveryApi }); expect(await api.listSecrets('')).toEqual(mockSecretsResult.items); }); + + it('should throw an error if the Vault API responds with an HTTP 404', async () => { + setupHandlers(); + const api = new VaultClient({ discoveryApi }); + await expect(api.listSecrets('test/not-found')).rejects.toThrow( + "No secrets found in path 'v1/secrets/test%2Fnot-found'", + ); + }); + + it('should throw an error if the Vault API responds with a non-successful HTTP status code', async () => { + setupHandlers(); + const api = new VaultClient({ discoveryApi }); + await expect(api.listSecrets('test/error')).rejects.toThrow( + 'Request failed with 400 Error', + ); + }); }); diff --git a/plugins/vault/src/api.ts b/plugins/vault/src/api.ts index bdd881e08c..84843c9176 100644 --- a/plugins/vault/src/api.ts +++ b/plugins/vault/src/api.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { DiscoveryApi, createApiRef } from '@backstage/core-plugin-api'; -import { NotFoundError } from '@backstage/errors'; +import { NotFoundError, ResponseError } from '@backstage/errors'; /** * @public @@ -75,9 +75,7 @@ export class VaultClient implements VaultApi { } else if (response.status === 404) { throw new NotFoundError(`No secrets found in path '${path}'`); } - throw new Error( - `Unexpected error while fetching secrets from path '${path}'`, - ); + throw await ResponseError.fromResponse(response); } async listSecrets(secretPath: string): Promise { diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx index 82a90f23e1..27cc0ed91e 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.test.tsx @@ -33,40 +33,28 @@ describe('EntityVaultTable', () => { let apis: TestApiRegistry; const mockBaseUrl = 'https://api-vault.com/api/vault'; const discoveryApi = UrlPatternDiscovery.compile(mockBaseUrl); - - const entityOk: ComponentEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'test', - description: 'This is the description', - annotations: { - 'vault.io/secrets-path': 'test/success', + const entity = (secretPath: string) => { + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test', + description: 'This is the description', + annotations: { + 'vault.io/secrets-path': secretPath, + }, }, - }, - spec: { - lifecycle: 'production', - owner: 'owner', - type: 'service', - }, + spec: { + lifecycle: 'production', + owner: 'owner', + type: 'service', + }, + } as ComponentEntity; }; - const entityNotOk: ComponentEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'test', - description: 'This is the description', - annotations: { - 'vault.io/secrets-path': 'test/error', - }, - }, - spec: { - lifecycle: 'production', - owner: 'owner', - type: 'service', - }, - }; + const entityOk = entity('test/success'); + const entityEmpty = entity('test/empty'); + const entityNotOk = entity('test/error'); const mockSecretsResult: { items: VaultSecret[] } = { items: [ @@ -91,7 +79,7 @@ describe('EntityVaultTable', () => { const { path } = req.params; if (path === 'test/success') { return res(ctx.json(mockSecretsResult)); - } else if (path === 'test/error') { + } else if (path === 'test/empty') { return res(ctx.json([])); } return res(ctx.status(400)); @@ -122,10 +110,25 @@ describe('EntityVaultTable', () => { setupHandlers(); const rendered = await renderInTestApp( - + , ); expect(rendered.getByText(/No secrets found/)).toBeInTheDocument(); }); + + it('should surface an appropriate error when the Vault API responds unsuccessfully', async () => { + setupHandlers(); + const rendered = await renderInTestApp( + + + , + ); + + expect( + rendered.getByText( + /Unexpected error while fetching secrets from path \'test\/error\'\: Request failed with 400 Error/, + ), + ).toBeInTheDocument(); + }); }); diff --git a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx index efc345b07f..9191d54b0b 100644 --- a/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx +++ b/plugins/vault/src/components/EntityVaultTable/EntityVaultTable.tsx @@ -81,7 +81,12 @@ export const EntityVaultTable = ({ entity }: { entity: Entity }) => { }); if (error) { - return {error.message}; + return ( + + Unexpected error while fetching secrets from path '{secretPath}':{' '} + {error.message} + + ); } return ( diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index 4d80489e99..af4665e980 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-xcmetrics +## 0.2.35-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.1 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + +## 0.2.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.12.4-next.0 + - @backstage/core-plugin-api@1.3.0 + - @backstage/errors@1.1.4 + - @backstage/theme@0.2.16 + ## 0.2.34 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index f4144693ae..775e884f4b 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.34", + "version": "0.2.35-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/scripts/assemble-manifest.js b/scripts/assemble-manifest.js index f68a83447d..f01bc7fd9b 100755 --- a/scripts/assemble-manifest.js +++ b/scripts/assemble-manifest.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2022 The Backstage Authors * diff --git a/scripts/check-docs-quality.js b/scripts/check-docs-quality.js index 10c4b99976..3dcbd6ef81 100755 --- a/scripts/check-docs-quality.js +++ b/scripts/check-docs-quality.js @@ -56,7 +56,7 @@ async function listFiles(dir = '') { // caused by the script. In CI, we want to ensure vale linter is run. async function exitIfMissingVale() { try { - // eslint-disable-next-line import/no-extraneous-dependencies + // eslint-disable-next-line @backstage/no-undeclared-imports await require('command-exists')('vale'); } catch (e) { if (process.env.CI) { diff --git a/scripts/check-if-release.js b/scripts/check-if-release.js index e7dabe14a4..c12b27b0ef 100755 --- a/scripts/check-if-release.js +++ b/scripts/check-if-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/create-github-release.js b/scripts/create-github-release.js index 4b3891c5ce..b64d7a9cb5 100755 --- a/scripts/create-github-release.js +++ b/scripts/create-github-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/create-release-tag.js b/scripts/create-release-tag.js index 28417024fd..311b46d4e5 100755 --- a/scripts/create-release-tag.js +++ b/scripts/create-release-tag.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2020 The Backstage Authors * diff --git a/scripts/list-deprecations.js b/scripts/list-deprecations.js index 8047158138..22aff96d67 100755 --- a/scripts/list-deprecations.js +++ b/scripts/list-deprecations.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const _ = require('lodash'); const fs = require('fs-extra'); diff --git a/scripts/prepare-release.js b/scripts/prepare-release.js index 973f4fad58..4019a71cf3 100755 --- a/scripts/prepare-release.js +++ b/scripts/prepare-release.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ /* * Copyright 2022 The Backstage Authors * diff --git a/scripts/snyk-github-issue-sync.ts b/scripts/snyk-github-issue-sync.ts index da64e2ea82..ea7d42a2a4 100755 --- a/scripts/snyk-github-issue-sync.ts +++ b/scripts/snyk-github-issue-sync.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ import { Octokit } from '@octokit/rest'; import minimist from 'minimist'; // Generated by GitHub workflow .github/workflows/snyk-github-issue-creator diff --git a/scripts/verify-api-reference.js b/scripts/verify-api-reference.js index 84a526604d..091e803c33 100755 --- a/scripts/verify-api-reference.js +++ b/scripts/verify-api-reference.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath } = require('path'); const { promises: fs } = require('fs'); diff --git a/scripts/verify-changesets.js b/scripts/verify-changesets.js index 9e3064eeac..ae3f07840a 100755 --- a/scripts/verify-changesets.js +++ b/scripts/verify-changesets.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath } = require('path'); const fs = require('fs-extra'); diff --git a/scripts/verify-links.js b/scripts/verify-links.js index 05ad387c37..7664cadad5 100755 --- a/scripts/verify-links.js +++ b/scripts/verify-links.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { resolve: resolvePath, join: joinPath, dirname } = require('path'); const fs = require('fs').promises; diff --git a/scripts/verify-lockfile-duplicates.js b/scripts/verify-lockfile-duplicates.js index cc22664219..820fba2ea5 100644 --- a/scripts/verify-lockfile-duplicates.js +++ b/scripts/verify-lockfile-duplicates.js @@ -15,7 +15,7 @@ * limitations under the License. */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable @backstage/no-undeclared-imports */ const { execFile: execFileCb } = require('child_process'); const { resolve: resolvePath, dirname: dirnamePath } = require('path'); diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 7c73f5d0cc..f2e0f1c96a 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2966,90 +2966,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-arm64@npm:1.3.30" +"@swc/core-darwin-arm64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-arm64@npm:1.3.34" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-x64@npm:1.3.30" +"@swc/core-darwin-x64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-x64@npm:1.3.34" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.30" +"@swc/core-linux-arm-gnueabihf@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.30" +"@swc/core-linux-arm64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.30" +"@swc/core-linux-arm64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.30" +"@swc/core-linux-x64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-musl@npm:1.3.30" +"@swc/core-linux-x64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-musl@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.30" +"@swc/core-win32-arm64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.30" +"@swc/core-win32-ia32-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.30" +"@swc/core-win32-x64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.30 - resolution: "@swc/core@npm:1.3.30" + version: 1.3.34 + resolution: "@swc/core@npm:1.3.34" dependencies: - "@swc/core-darwin-arm64": 1.3.30 - "@swc/core-darwin-x64": 1.3.30 - "@swc/core-linux-arm-gnueabihf": 1.3.30 - "@swc/core-linux-arm64-gnu": 1.3.30 - "@swc/core-linux-arm64-musl": 1.3.30 - "@swc/core-linux-x64-gnu": 1.3.30 - "@swc/core-linux-x64-musl": 1.3.30 - "@swc/core-win32-arm64-msvc": 1.3.30 - "@swc/core-win32-ia32-msvc": 1.3.30 - "@swc/core-win32-x64-msvc": 1.3.30 + "@swc/core-darwin-arm64": 1.3.34 + "@swc/core-darwin-x64": 1.3.34 + "@swc/core-linux-arm-gnueabihf": 1.3.34 + "@swc/core-linux-arm64-gnu": 1.3.34 + "@swc/core-linux-arm64-musl": 1.3.34 + "@swc/core-linux-x64-gnu": 1.3.34 + "@swc/core-linux-x64-musl": 1.3.34 + "@swc/core-win32-arm64-msvc": 1.3.34 + "@swc/core-win32-ia32-msvc": 1.3.34 + "@swc/core-win32-x64-msvc": 1.3.34 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -3071,7 +3071,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 157a8ae43ebc73fa28d53e913fd7fc879289d5479ba5ea0c5e9abad0b379ca7e292d45f4f07bfd3ec0ff1998b55f300737724dfe463f1f7b361661e083db950c + checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 languageName: node linkType: hard @@ -6783,9 +6783,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 86ac2a85a2..345c28a8b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -217,14 +217,16 @@ __metadata: languageName: node linkType: hard -"@asyncapi/avro-schema-parser@npm:^0.3.0": - version: 0.3.0 - resolution: "@asyncapi/avro-schema-parser@npm:0.3.0" - checksum: 3086bc16a634600fe4d7c83f52f9558684c0d79193958fcb9275cacfb550700eaa718aa9ed1d3c89d1d77253f67e0f33ea91e137ef08aa722d67ded9373bf142 +"@asyncapi/avro-schema-parser@npm:^1.1.0": + version: 1.1.0 + resolution: "@asyncapi/avro-schema-parser@npm:1.1.0" + dependencies: + avsc: ^5.7.3 + checksum: 31bb6285a49f255e809088164ac4638103b2ec3e761c9c85be116af8abd9fe429626ba79ba6b3899d3823a77216741d9d793841e600145f2956328f3ce45a0e0 languageName: node linkType: hard -"@asyncapi/openapi-schema-parser@npm:^2.0.0": +"@asyncapi/openapi-schema-parser@npm:^2.0.1": version: 2.0.1 resolution: "@asyncapi/openapi-schema-parser@npm:2.0.1" dependencies: @@ -233,12 +235,12 @@ __metadata: languageName: node linkType: hard -"@asyncapi/parser@npm:^1.17.0": - version: 1.17.0 - resolution: "@asyncapi/parser@npm:1.17.0" +"@asyncapi/parser@npm:^1.18.0": + version: 1.18.0 + resolution: "@asyncapi/parser@npm:1.18.0" dependencies: "@apidevtools/json-schema-ref-parser": ^9.0.6 - "@asyncapi/specs": ^3.2.0 + "@asyncapi/specs": ^4.1.0 "@fmvilas/pseudo-yaml-ast": ^0.3.1 ajv: ^6.10.1 js-yaml: ^3.13.1 @@ -246,147 +248,138 @@ __metadata: lodash.clonedeep: ^4.5.0 node-fetch: ^2.6.0 tiny-merge-patch: ^0.1.2 - checksum: 6ac0bd3c9c90abf331cfdfb054dab047cf0324ee803633c2abc6dad96b12c64d033e4fb94907906adfb521ba16e9b23083b2a6acc7719ccd22154a7867046a95 + checksum: 7e08cae52990ce97299170faf99aaf27a8e2e02e6b03df28518d256f5687f394c26fd0a4aba235514ed4e3c2fd081a79321a489c20987ed22122afdb0b9ea0dd languageName: node linkType: hard -"@asyncapi/react-component@npm:1.0.0-next.44": - version: 1.0.0-next.44 - resolution: "@asyncapi/react-component@npm:1.0.0-next.44" +"@asyncapi/react-component@npm:1.0.0-next.47": + version: 1.0.0-next.47 + resolution: "@asyncapi/react-component@npm:1.0.0-next.47" dependencies: - "@asyncapi/avro-schema-parser": ^0.3.0 - "@asyncapi/openapi-schema-parser": ^2.0.0 - "@asyncapi/parser": ^1.17.0 + "@asyncapi/avro-schema-parser": ^1.1.0 + "@asyncapi/openapi-schema-parser": ^2.0.1 + "@asyncapi/parser": ^1.18.0 highlight.js: ^10.7.2 isomorphic-dompurify: ^0.13.0 marked: ^4.0.14 openapi-sampler: ^1.2.1 - react-icons: ^4.4.0 use-resize-observer: ^8.0.0 peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 1d96db3bc6a4655884969a7639467836376c028df1a00f8930adf4e1b6ecb43e6a2d61df5c68e63d6c105d319fecb3f2ac0e4146274a81a874fbde17f4dbac1c + checksum: 837b6378f1188945a0e92d93efe71691a8dad120fad5624b58b325ec86c51435b874464ec0c47308ffacda9ee4d77ad8217881584bd74081f6db2211f09cc60c languageName: node linkType: hard -"@asyncapi/specs@npm:^3.2.0": - version: 3.2.0 - resolution: "@asyncapi/specs@npm:3.2.0" - checksum: 09971262aefc8844ab3e7c0c3652711862ac562dd5d614f23b496185690430a81df8e50eddba657f4141e0fd9548ef622fe6c20f4e3dec8054be23f774798335 - languageName: node - linkType: hard - -"@aws-crypto/crc32@npm:2.0.0": - version: 2.0.0 - resolution: "@aws-crypto/crc32@npm:2.0.0" +"@asyncapi/specs@npm:^4.1.0": + version: 4.1.0 + resolution: "@asyncapi/specs@npm:4.1.0" dependencies: - "@aws-crypto/util": ^2.0.0 - "@aws-sdk/types": ^3.1.0 - tslib: ^1.11.1 - checksum: 88ab906da8304a430c655496e363835f3c7ca870db0dec50bb9d53ed0f446337de60c85ba7baa4528c8363bee708474785649262ebfde23a1e099eb69318b53e + "@types/json-schema": ^7.0.11 + checksum: 6e95f3c1ef7267480cdfc69f5a015f63b9101874289e31843a629346a3ea07490e3043b296a089bf3458e877c664d83d4b4738dcb53d37d7e13b75c7bc08c879 languageName: node linkType: hard -"@aws-crypto/crc32c@npm:2.0.0": - version: 2.0.0 - resolution: "@aws-crypto/crc32c@npm:2.0.0" +"@aws-crypto/crc32@npm:3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/crc32@npm:3.0.0" dependencies: - "@aws-crypto/util": ^2.0.0 - "@aws-sdk/types": ^3.1.0 + "@aws-crypto/util": ^3.0.0 + "@aws-sdk/types": ^3.222.0 tslib: ^1.11.1 - checksum: 776e1e61b3bde018b815d3973774a4ec3cd88c282046e49bb5a2625ac7db923068aad708a8e4c21b62a80e50a5c58324a32621b9ba82b7b2ecab66370c4fe893 + checksum: 9fdb3e837fc54119b017ea34fd0a6d71d2c88075d99e1e818a5158e0ad30ced67ddbcc423a11ceeef6cc465ab5ffd91830acab516470b48237ca7abd51be9642 languageName: node linkType: hard -"@aws-crypto/ie11-detection@npm:^2.0.0": - version: 2.0.2 - resolution: "@aws-crypto/ie11-detection@npm:2.0.2" +"@aws-crypto/crc32c@npm:3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/crc32c@npm:3.0.0" + dependencies: + "@aws-crypto/util": ^3.0.0 + "@aws-sdk/types": ^3.222.0 + tslib: ^1.11.1 + checksum: 0a116b5d1c5b09a3dde65aab04a07b32f543e87b68f2d175081e3f4a1a17502343f223d691dd883ace1ddce65cd40093673e7c7415dcd99062202ba87ffb4038 + languageName: node + linkType: hard + +"@aws-crypto/ie11-detection@npm:^3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/ie11-detection@npm:3.0.0" dependencies: tslib: ^1.11.1 - checksum: 713293deea8eefd3ab43dc05e62228571d27754e7293f8ec2fd8a0c693fbbfc55213e6599387776e3cdbc951965dc62e24e92b9c4a853e4a50d00ae6a9f6b2bd + checksum: 299b2ddd46eddac1f2d54d91386ceb37af81aef8a800669281c73d634ed17fd855dcfb8b3157f2879344b93a2666a6d602550eb84b71e4d7868100ad6da8f803 languageName: node linkType: hard -"@aws-crypto/sha1-browser@npm:2.0.0": - version: 2.0.0 - resolution: "@aws-crypto/sha1-browser@npm:2.0.0" +"@aws-crypto/sha1-browser@npm:3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/sha1-browser@npm:3.0.0" dependencies: - "@aws-crypto/ie11-detection": ^2.0.0 - "@aws-crypto/supports-web-crypto": ^2.0.0 - "@aws-sdk/types": ^3.1.0 + "@aws-crypto/ie11-detection": ^3.0.0 + "@aws-crypto/supports-web-crypto": ^3.0.0 + "@aws-crypto/util": ^3.0.0 + "@aws-sdk/types": ^3.222.0 "@aws-sdk/util-locate-window": ^3.0.0 "@aws-sdk/util-utf8-browser": ^3.0.0 tslib: ^1.11.1 - checksum: 72c0b24800cd79328fef934553e7a5d5929c90877d7e9a661614542dd29d0d99ee1594bd59fc028ee9ec595d77df56645a396c6336cff3c7784a564302d4a254 + checksum: 78c379e105a0c4e7b2ed745dffd8f55054d7dde8b350b61de682bbc3cd081a50e2f87861954fa9cd53c7ea711ebca1ca0137b14cb36483efc971f60f573cf129 languageName: node linkType: hard -"@aws-crypto/sha256-browser@npm:2.0.0": - version: 2.0.0 - resolution: "@aws-crypto/sha256-browser@npm:2.0.0" +"@aws-crypto/sha256-browser@npm:3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/sha256-browser@npm:3.0.0" dependencies: - "@aws-crypto/ie11-detection": ^2.0.0 - "@aws-crypto/sha256-js": ^2.0.0 - "@aws-crypto/supports-web-crypto": ^2.0.0 - "@aws-crypto/util": ^2.0.0 - "@aws-sdk/types": ^3.1.0 + "@aws-crypto/ie11-detection": ^3.0.0 + "@aws-crypto/sha256-js": ^3.0.0 + "@aws-crypto/supports-web-crypto": ^3.0.0 + "@aws-crypto/util": ^3.0.0 + "@aws-sdk/types": ^3.222.0 "@aws-sdk/util-locate-window": ^3.0.0 "@aws-sdk/util-utf8-browser": ^3.0.0 tslib: ^1.11.1 - checksum: 7bc1ff042d0c53a46c0fc3824bd97fb3ed1df7dc030b8a995889471052860b8c8ade469c97866fafd8249a3144d0f48b0f1054f357e2b403606009381c4b8f0e + checksum: ca89456bf508db2e08060a7f656460db97ac9a15b11e39d6fa7665e2b156508a1758695bff8e82d0a00178d6ac5c36f35eb4bcfac2e48621265224ca14a19bd2 languageName: node linkType: hard -"@aws-crypto/sha256-js@npm:2.0.0": - version: 2.0.0 - resolution: "@aws-crypto/sha256-js@npm:2.0.0" +"@aws-crypto/sha256-js@npm:3.0.0, @aws-crypto/sha256-js@npm:^3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/sha256-js@npm:3.0.0" dependencies: - "@aws-crypto/util": ^2.0.0 - "@aws-sdk/types": ^3.1.0 + "@aws-crypto/util": ^3.0.0 + "@aws-sdk/types": ^3.222.0 tslib: ^1.11.1 - checksum: e4abf9baec6bed19d380f92a999a41ac5bdd8890dfd45971d29054c298854c5b7087e7de633413f2e64618ef8238ccf4c0b75797c73063c74bbba3cb5d8b2581 + checksum: 644ded32ea310237811afae873d3c7320739cb6f6cc39dced9c94801379e68e5ee2cca0c34f0384793fa9e750a7e0a5e2468f95754bd08e6fd72ab833c8fe23c languageName: node linkType: hard -"@aws-crypto/sha256-js@npm:^2.0.0": - version: 2.0.2 - resolution: "@aws-crypto/sha256-js@npm:2.0.2" - dependencies: - "@aws-crypto/util": ^2.0.2 - "@aws-sdk/types": ^3.110.0 - tslib: ^1.11.1 - checksum: 9125ec65a2b05fce908ac2289ba97b995a299f2d717684804211df8e8bcffd8cd9b8861582240655b88f2255c46fcee34026f75c057ffb22f44b6a76cd43f65a - languageName: node - linkType: hard - -"@aws-crypto/supports-web-crypto@npm:^2.0.0": - version: 2.0.2 - resolution: "@aws-crypto/supports-web-crypto@npm:2.0.2" +"@aws-crypto/supports-web-crypto@npm:^3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/supports-web-crypto@npm:3.0.0" dependencies: tslib: ^1.11.1 - checksum: 03d04d29292dc1b76db9bc6becd05f52fa79adee0ec084f971b0767f7e73250dd0422bea57636015f8c27f38aefcd1d9c58800a4749cf35339296c8d670f3ccb + checksum: 35479a1558db9e9a521df6877a99f95670e972c602f2a0349303477e5d638a5baf569fb037c853710e382086e6fd77e8ed58d3fb9b49f6e1186a9d26ce7be006 languageName: node linkType: hard -"@aws-crypto/util@npm:^2.0.0, @aws-crypto/util@npm:^2.0.2": - version: 2.0.2 - resolution: "@aws-crypto/util@npm:2.0.2" +"@aws-crypto/util@npm:^3.0.0": + version: 3.0.0 + resolution: "@aws-crypto/util@npm:3.0.0" dependencies: - "@aws-sdk/types": ^3.110.0 + "@aws-sdk/types": ^3.222.0 "@aws-sdk/util-utf8-browser": ^3.0.0 tslib: ^1.11.1 - checksum: 13cb33a39005b09c062398d361043c2224bc8ba42b1432bad52e15bc4bf9ffad4facdddc394b3cc71b3fb8d86a7ec325fd1afa107b5fde0dab84a7e32d311d7f + checksum: d29d5545048721aae3d60b236708535059733019a105f8a64b4e4a8eab7cf8dde1546dc56bff7de20d36140a4d1f0f4693e639c5732a7059273a7b1e56354776 languageName: node linkType: hard -"@aws-sdk/abort-controller@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/abort-controller@npm:3.226.0" +"@aws-sdk/abort-controller@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/abort-controller@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 44045b60c7697ed76bcbfbe3f7f4bb019f139d2337e77d8ce79d98bca17c1245e2d33934bba04fe8e2d462b729124ba4414a589ed9275c07f2bfefd3a0850184 + checksum: fca54be92f6cbfe8f0675aba19a50960376506a4c9aaa9c44220e8c29a7b3c8c74198537f831c1d4818ec686df97af86d055d8f3265c3a6fde56bbf593241c47 languageName: node linkType: hard @@ -409,483 +402,477 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-cognito-identity@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.245.0" +"@aws-sdk/client-cognito-identity@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.261.0" dependencies: - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/client-sts": 3.245.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/credential-provider-node": 3.245.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-signing": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.261.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/credential-provider-node": 3.261.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-signing": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 4142ba1b7a3c11f785d5da527a743d6a9352f6f97ae983e6f3ee0abf5a1cd755c2196981cbc2f6052686bf820a68f062117c682a5126e55acaacebc5cab862e6 + checksum: edbaacaa9b2576376aedca110ba6267af25005922e23e9d7c5b0d00572ab758b47493f30bf6223c9462e31b236f7d6194786be0d6e79676726a28d74a6de8989 languageName: node linkType: hard "@aws-sdk/client-s3@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/client-s3@npm:3.245.0" + version: 3.261.0 + resolution: "@aws-sdk/client-s3@npm:3.261.0" dependencies: - "@aws-crypto/sha1-browser": 2.0.0 - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/client-sts": 3.245.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/credential-provider-node": 3.245.0 - "@aws-sdk/eventstream-serde-browser": 3.226.0 - "@aws-sdk/eventstream-serde-config-resolver": 3.226.0 - "@aws-sdk/eventstream-serde-node": 3.226.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-blob-browser": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/hash-stream-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/md5-js": 3.226.0 - "@aws-sdk/middleware-bucket-endpoint": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-expect-continue": 3.226.0 - "@aws-sdk/middleware-flexible-checksums": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-location-constraint": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-sdk-s3": 3.231.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-signing": 3.226.0 - "@aws-sdk/middleware-ssec": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/signature-v4-multi-region": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha1-browser": 3.0.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.261.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/credential-provider-node": 3.261.0 + "@aws-sdk/eventstream-serde-browser": 3.258.0 + "@aws-sdk/eventstream-serde-config-resolver": 3.257.0 + "@aws-sdk/eventstream-serde-node": 3.258.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-blob-browser": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/hash-stream-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/md5-js": 3.258.0 + "@aws-sdk/middleware-bucket-endpoint": 3.259.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-expect-continue": 3.257.0 + "@aws-sdk/middleware-flexible-checksums": 3.259.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-location-constraint": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-sdk-s3": 3.257.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-signing": 3.257.0 + "@aws-sdk/middleware-ssec": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/signature-v4-multi-region": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-stream-browser": 3.226.0 - "@aws-sdk/util-stream-node": 3.226.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 - "@aws-sdk/util-waiter": 3.226.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-stream-browser": 3.258.0 + "@aws-sdk/util-stream-node": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 + "@aws-sdk/util-waiter": 3.257.0 "@aws-sdk/xml-builder": 3.201.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: 7aaec8fdcfa1390222e6fc55d7314dbebab05c1afad8e580cd5137f71bb6cef7ffaca113b117af22ee2ac110b03fbf7eec173f16cf093b0e1366f218169db7a4 + checksum: 3600a38f6828b4fd3e14adf1f5aeb2fbb6693d43f4dd4f8be384adbf2b2218d50aa034f19c4399dececfa072833fa7ddd680c23c4c8ad30e04c0045f37d859ee languageName: node linkType: hard "@aws-sdk/client-sqs@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/client-sqs@npm:3.245.0" + version: 3.261.0 + resolution: "@aws-sdk/client-sqs@npm:3.261.0" dependencies: - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/client-sts": 3.245.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/credential-provider-node": 3.245.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/md5-js": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-sdk-sqs": 3.226.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-signing": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/client-sts": 3.261.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/credential-provider-node": 3.261.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/md5-js": 3.258.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-sdk-sqs": 3.257.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-signing": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: 994c18f001763e63b8cfd86ddcb8c7c8460f8bb0507759037315d15a37e2a2e49833091ec6db7b4181323a389b3b14085cf87eb00c1980479f1e184d63d7de74 + checksum: b15130b021f1af1109236abda0fb83232a37b8cb147bf59e3f09b3f44db6934d19bb3633eeac9c7302b9019714d53d47acc0e66df90ef848f518cf0d11661f15 languageName: node linkType: hard -"@aws-sdk/client-sso-oidc@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/client-sso-oidc@npm:3.245.0" +"@aws-sdk/client-sso-oidc@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/client-sso-oidc@npm:3.261.0" dependencies: - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 6f72ee0df276f8c4019be4d9b3fa1b2cbab7744b13f434f07c9314303290334296be1148276266715ef3cfb37e83ced448fd9d6bb34d09bd21ed41d0a83598dc + checksum: d33870aed0db77246812b99d05d5536df4b51a36fc0f1717aa883e82c5c8460bb867a6a3b817b06f41e86732390305dced75f99aee1d58ae3635102a89562ae7 languageName: node linkType: hard -"@aws-sdk/client-sso@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/client-sso@npm:3.245.0" +"@aws-sdk/client-sso@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/client-sso@npm:3.261.0" dependencies: - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: e7dd235ee13465438a181c5de2f5bfc1acdaa12a07db74a3255dbb580004c33544d6773252b164dda2e2357ea83f3985afd060dfe42d6064732d36750764eda1 + checksum: aa2b71a0be6c5ca92940eacdb008d89c007b595f8c5cb80ff7c5c697d83e1de44432463f5d20b7074939c806612165c47345b197e8dd1743f523858117a4b70b languageName: node linkType: hard -"@aws-sdk/client-sts@npm:3.245.0, @aws-sdk/client-sts@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/client-sts@npm:3.245.0" +"@aws-sdk/client-sts@npm:3.261.0, @aws-sdk/client-sts@npm:^3.208.0": + version: 3.261.0 + resolution: "@aws-sdk/client-sts@npm:3.261.0" dependencies: - "@aws-crypto/sha256-browser": 2.0.0 - "@aws-crypto/sha256-js": 2.0.0 - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/credential-provider-node": 3.245.0 - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/hash-node": 3.226.0 - "@aws-sdk/invalid-dependency": 3.226.0 - "@aws-sdk/middleware-content-length": 3.226.0 - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/middleware-host-header": 3.226.0 - "@aws-sdk/middleware-logger": 3.226.0 - "@aws-sdk/middleware-recursion-detection": 3.226.0 - "@aws-sdk/middleware-retry": 3.235.0 - "@aws-sdk/middleware-sdk-sts": 3.226.0 - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/middleware-signing": 3.226.0 - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/middleware-user-agent": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-crypto/sha256-browser": 3.0.0 + "@aws-crypto/sha256-js": 3.0.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/credential-provider-node": 3.261.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/hash-node": 3.257.0 + "@aws-sdk/invalid-dependency": 3.257.0 + "@aws-sdk/middleware-content-length": 3.257.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/middleware-host-header": 3.257.0 + "@aws-sdk/middleware-logger": 3.257.0 + "@aws-sdk/middleware-recursion-detection": 3.257.0 + "@aws-sdk/middleware-retry": 3.259.0 + "@aws-sdk/middleware-sdk-sts": 3.257.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/middleware-signing": 3.257.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/middleware-user-agent": 3.257.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-body-length-browser": 3.188.0 "@aws-sdk/util-body-length-node": 3.208.0 - "@aws-sdk/util-defaults-mode-browser": 3.234.0 - "@aws-sdk/util-defaults-mode-node": 3.234.0 - "@aws-sdk/util-endpoints": 3.245.0 - "@aws-sdk/util-retry": 3.229.0 - "@aws-sdk/util-user-agent-browser": 3.226.0 - "@aws-sdk/util-user-agent-node": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/util-defaults-mode-browser": 3.261.0 + "@aws-sdk/util-defaults-mode-node": 3.261.0 + "@aws-sdk/util-endpoints": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 + "@aws-sdk/util-user-agent-browser": 3.257.0 + "@aws-sdk/util-user-agent-node": 3.259.0 + "@aws-sdk/util-utf8": 3.254.0 fast-xml-parser: 4.0.11 tslib: ^2.3.1 - checksum: 3b052be86063978b47b2f4459062ea23a6d94c81951a97428a5445ff062d642a3460114cbf1b20d3925db0667d893db40cbe30b1b8b58a4d749c75d117aab460 + checksum: e7be888c97351bb3b52e50de5e6830849c97c9d2b2ad2b14daea66f7dd2e7a4eaae26ccb78aeb874b1719c73a8d8ccf2bb02915eca4cabeb34226e1a10ae1ebd languageName: node linkType: hard -"@aws-sdk/config-resolver@npm:3.234.0": - version: 3.234.0 - resolution: "@aws-sdk/config-resolver@npm:3.234.0" +"@aws-sdk/config-resolver@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/config-resolver@npm:3.259.0" dependencies: - "@aws-sdk/signature-v4": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/signature-v4": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-config-provider": 3.208.0 - "@aws-sdk/util-middleware": 3.226.0 + "@aws-sdk/util-middleware": 3.257.0 tslib: ^2.3.1 - checksum: a72bdb1748d7f04c95436ab1e8650b51c1bfd2745114e52f7d05339c61bb6a859306be0c6cc0034ecf4f3b29a2d68b48fe362762a58c90ec55a3444b93b5700d + checksum: c461dfd62291c8dbc3394d586aa44a14326c0a9f02e4cc84dfa6569c6003890d21343aaa28a067337949837f7e2c2e3533465e3e2e5f2ee3e42bb30cc69de0d4 languageName: node linkType: hard -"@aws-sdk/credential-provider-cognito-identity@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.245.0" +"@aws-sdk/credential-provider-cognito-identity@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.261.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.245.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/client-cognito-identity": 3.261.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: af9ce2a19426056139c380fa2a016d5abb42117e262dc5c3f4741eb1f2d15b394e9b178d6efb2e32f59cd723c6090da769975505368fbbe79b8eb9258c6961a8 + checksum: 678098f0079cef01ed10c7c06f838b30ec50a047dd67cadd898a134347c31d9dfc9cdd18880eeae26f2d1f700b8d5ae120181f0b1889a20da981076edef5c2c6 languageName: node linkType: hard -"@aws-sdk/credential-provider-env@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.226.0" +"@aws-sdk/credential-provider-env@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/credential-provider-env@npm:3.257.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 4f764d8d07ba1f65503ed2440ebfbccf98c141b11a087a582ea606d06bc764c91641b4ec505ab0d4750025a01128b041d9514a3ec868c385f038b5373b513293 + checksum: e268c46ff374eddb5cd5bef62a8b969a5bfd5202e15122ecbd2baa7882c99f75c2e2b6dfc0c294fcfc331e9e2028620c827278f1eec6f7158c30f079ae67dc5f languageName: node linkType: hard -"@aws-sdk/credential-provider-imds@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/credential-provider-imds@npm:3.226.0" +"@aws-sdk/credential-provider-imds@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/credential-provider-imds@npm:3.259.0" dependencies: - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 tslib: ^2.3.1 - checksum: c0480ca127e6715ebf98ff41a8ea47d139166b8632582782df46fc9e568ff579cfc0768af80082ae6eea3eb6750edb41c4a4c39281b777c578fdb7f8ef8b641c + checksum: 7149bb155e9f169f6d9a4e17d16c683b5eed6f71871230f1c786b884f22fe438b3f29e6179a5538ad540f025d2eb3cfa1a4d9a1bd1e1ec495a539f8d164903da languageName: node linkType: hard -"@aws-sdk/credential-provider-ini@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.245.0" +"@aws-sdk/credential-provider-ini@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.261.0" dependencies: - "@aws-sdk/credential-provider-env": 3.226.0 - "@aws-sdk/credential-provider-imds": 3.226.0 - "@aws-sdk/credential-provider-process": 3.226.0 - "@aws-sdk/credential-provider-sso": 3.245.0 - "@aws-sdk/credential-provider-web-identity": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/credential-provider-env": 3.257.0 + "@aws-sdk/credential-provider-imds": 3.259.0 + "@aws-sdk/credential-provider-process": 3.257.0 + "@aws-sdk/credential-provider-sso": 3.261.0 + "@aws-sdk/credential-provider-web-identity": 3.257.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 35fcdb231efb573c60c25e67a27f64ca892ebab7931e715406826a4d3f87caecd525945f45ecaf7fb7e09a87a744678aba60249c74681160c9fb9d66c0490bf5 + checksum: 72834195a9a2fad9d6a8011d904ed0a59b29c043bcc98e226b2381d123c57b9b528dd924aa2c94283e38cbddb98198892c0f428b363565678ca992276062cc8d languageName: node linkType: hard -"@aws-sdk/credential-provider-node@npm:3.245.0, @aws-sdk/credential-provider-node@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.245.0" +"@aws-sdk/credential-provider-node@npm:3.261.0, @aws-sdk/credential-provider-node@npm:^3.208.0": + version: 3.261.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.261.0" dependencies: - "@aws-sdk/credential-provider-env": 3.226.0 - "@aws-sdk/credential-provider-imds": 3.226.0 - "@aws-sdk/credential-provider-ini": 3.245.0 - "@aws-sdk/credential-provider-process": 3.226.0 - "@aws-sdk/credential-provider-sso": 3.245.0 - "@aws-sdk/credential-provider-web-identity": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/credential-provider-env": 3.257.0 + "@aws-sdk/credential-provider-imds": 3.259.0 + "@aws-sdk/credential-provider-ini": 3.261.0 + "@aws-sdk/credential-provider-process": 3.257.0 + "@aws-sdk/credential-provider-sso": 3.261.0 + "@aws-sdk/credential-provider-web-identity": 3.257.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: a9bd115016fc7ce7f2cb50c5cafcd759f861362bb9dd9629e4ea0056519d5b26ad256f6d1d84ef3327c75bef442de8c0e4b54b215870512b43c92866ed0f1403 + checksum: af393f142f1305438f5ac5be79a120ad1566d57edca8b1577dc0fcfe50bfb31c721de2d04dd49abbf3086676ad5c4b809d136841e2e25451facf9599dda7322c languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.226.0" +"@aws-sdk/credential-provider-process@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/credential-provider-process@npm:3.257.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 3ad24e2784ae7929f8932a187e0a5a06fc62d31ccb393fd2d9fa86d75c1109809c96b69edb17c3d7bd7d087b97662818d5320742a4cd70add06999a3b2ec3a53 + checksum: cb34261ae87463245e4cc3ddab306201c52a8fbcfedc122ae9782bdf9263ab8fabc33cde028def52d069452a842338033829aaecfec2d0fc00547513a76c9b6f languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.245.0" +"@aws-sdk/credential-provider-sso@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.261.0" dependencies: - "@aws-sdk/client-sso": 3.245.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/token-providers": 3.245.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/client-sso": 3.261.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/token-providers": 3.261.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 95358504631d5451520d5090e7fb337b40dfc12ab30dd84d979165d881f2762798828003b13adcb35921223bf3a498b0e70b7a94ebc14e8b16a4f0adacded8f1 + checksum: 0f3fc6ceb69e537f2e5751283aac473dcc5a4f8da798b0340995cb5996ca8201844c2f5b6cdcaa7ce642e1375cbdd039fa4b9962b84f27d500eaaa1f80725199 languageName: node linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.226.0" +"@aws-sdk/credential-provider-web-identity@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.257.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: f536d9af3d900eee31b6e7966ff827713fd5f661ae477f0911eebdac3e544eb5a732df0be0c9162058943e0aeb89333c97a1758236e8f9760c5e87280fd926fa + checksum: 2d3ee4975af680337cd6a9f25b6eb874201f4787ddc0217f80cb7ebb36c70424108fa8c04e5a9f0f8c2130d06685a3de3938c41b8c78e238b9faeb348c0cd361 languageName: node linkType: hard "@aws-sdk/credential-providers@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/credential-providers@npm:3.245.0" + version: 3.261.0 + resolution: "@aws-sdk/credential-providers@npm:3.261.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.245.0 - "@aws-sdk/client-sso": 3.245.0 - "@aws-sdk/client-sts": 3.245.0 - "@aws-sdk/credential-provider-cognito-identity": 3.245.0 - "@aws-sdk/credential-provider-env": 3.226.0 - "@aws-sdk/credential-provider-imds": 3.226.0 - "@aws-sdk/credential-provider-ini": 3.245.0 - "@aws-sdk/credential-provider-node": 3.245.0 - "@aws-sdk/credential-provider-process": 3.226.0 - "@aws-sdk/credential-provider-sso": 3.245.0 - "@aws-sdk/credential-provider-web-identity": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/client-cognito-identity": 3.261.0 + "@aws-sdk/client-sso": 3.261.0 + "@aws-sdk/client-sts": 3.261.0 + "@aws-sdk/credential-provider-cognito-identity": 3.261.0 + "@aws-sdk/credential-provider-env": 3.257.0 + "@aws-sdk/credential-provider-imds": 3.259.0 + "@aws-sdk/credential-provider-ini": 3.261.0 + "@aws-sdk/credential-provider-node": 3.261.0 + "@aws-sdk/credential-provider-process": 3.257.0 + "@aws-sdk/credential-provider-sso": 3.261.0 + "@aws-sdk/credential-provider-web-identity": 3.257.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: a6923907ce97232cf87565e5fc0dac872061d2f065f530f7c91d1693472dd26667a91a662283994b3886a84b557f45e8627d0c847a88ffa0fdf2458a0180bd43 + checksum: 56880bab2a99c2c9710622be905091c1316dbcd9ce44c5a567021ce809134cf52d5a920649ab715157b408ff73cf03bdee4da4d410c448ffa72b90bb9a9b03db languageName: node linkType: hard -"@aws-sdk/eventstream-codec@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/eventstream-codec@npm:3.226.0" +"@aws-sdk/eventstream-codec@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/eventstream-codec@npm:3.258.0" dependencies: - "@aws-crypto/crc32": 2.0.0 - "@aws-sdk/types": 3.226.0 + "@aws-crypto/crc32": 3.0.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-hex-encoding": 3.201.0 tslib: ^2.3.1 - checksum: 3b3a584c02bcf6cfe35e2ed562e8d82844a51c1efd2f9d79a72ecf60ba9a63a51c568c8b5a49cdfb6c49fe655be0454c082098285378c66494109dbf7b5bb28f + checksum: b2fca764b9c105a355a18af565c3a5bbd50ce6cf385b86668c1451f429a1fac31114bf88eec3d4ea2160a368f48e06f6b3ce83d273035e4824464de9c322f9d8 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-browser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/eventstream-serde-browser@npm:3.226.0" +"@aws-sdk/eventstream-serde-browser@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/eventstream-serde-browser@npm:3.258.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/eventstream-serde-universal": 3.258.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 12530898d3debe33fbc73c6b68c7a889e4c3e29c183180d9d012e9b3761af1fd58feaa9a6e8069ccf380442c7d71ad6f36d5f0af078ae6d29af944ca6f4a9610 + checksum: 3155f6bc39ef914be1950d8ba310029d5f8ffacaf9a516b20da4890d68b2bde6c636367bb4391c12ce4a3518041aca1afae0179aa5d76f9208133e7423bd86d9 languageName: node linkType: hard -"@aws-sdk/eventstream-serde-config-resolver@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.226.0" +"@aws-sdk/eventstream-serde-config-resolver@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/eventstream-serde-config-resolver@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 2438bfd3bf00e401caa79c2b874be6ecfac24db74f3ec9e1064a3d5c09a7cfe0fa9c0086e30ee3bc8853f550efc6c6ecb2936caafd238478870a803863fbea23 + checksum: 6658916cebfbdc74407cfdf1bda622bd9c7731a5f855b9cfb8870e3dd558f802ccc99ee30e9dcc05109d2a4c253cac799506afad5947c8526ab49973a567c0fb languageName: node linkType: hard -"@aws-sdk/eventstream-serde-node@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/eventstream-serde-node@npm:3.226.0" +"@aws-sdk/eventstream-serde-node@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/eventstream-serde-node@npm:3.258.0" dependencies: - "@aws-sdk/eventstream-serde-universal": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/eventstream-serde-universal": 3.258.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 89c2154fb4bb544f87e5fdda37cc99f724125892417d78763a98a0a4390b2ba89e8a57521a57b213827688ce8d8bc14971ae87f1137cc26d9f3ebbae142d5a96 + checksum: 298b60866c8b10cec812766f0a8f9fba482dcd19b48c0c6dceb5bda10e85a64c5c1216a61d288c0fd3b7be4a6e1dfba4f30a41b01a6bbb60a1cb419b21f0902a languageName: node linkType: hard -"@aws-sdk/eventstream-serde-universal@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/eventstream-serde-universal@npm:3.226.0" +"@aws-sdk/eventstream-serde-universal@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/eventstream-serde-universal@npm:3.258.0" dependencies: - "@aws-sdk/eventstream-codec": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/eventstream-codec": 3.258.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: da1eea2d8b0f6972a5016ca66b2a8da0e2e72b8449a661c8cf4678894e22bcef20d5c1534c5c5a22b4c7d1d242bf894b7220c8d712123e092efa8c5fa8aca02f + checksum: 038ed604878f31478c2b00e86fdeeeee38905349be2fbf8104954d176b94996863e5e6e8a15c4849acac7ccaa537718762c1619d436ccef87c8a8b0bbf9d68cb languageName: node linkType: hard @@ -902,59 +889,61 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/fetch-http-handler@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/fetch-http-handler@npm:3.226.0" +"@aws-sdk/fetch-http-handler@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/fetch-http-handler@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/querystring-builder": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/querystring-builder": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-base64": 3.208.0 tslib: ^2.3.1 - checksum: f12ed12088aee05e4c6a742356017f55f26fec740c12c4d89c4eb283203171d032d99c9fa45fb28cc7798b35410cc55736df1c78d8eea014667e489f1b276f3a + checksum: de25f542db072225c23403254be7ff4e642f12e348eb703cdb30a5e9b0ac5e4f18930947490f6bb27a31b8f8a462abfdd7b9344b16e41b6b52e1fe969ac95396 languageName: node linkType: hard -"@aws-sdk/hash-blob-browser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/hash-blob-browser@npm:3.226.0" +"@aws-sdk/hash-blob-browser@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/hash-blob-browser@npm:3.257.0" dependencies: "@aws-sdk/chunked-blob-reader": 3.188.0 "@aws-sdk/chunked-blob-reader-native": 3.208.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 98fecc0646a37bfb541a2e8bd1da27f0b208f9d51e6efc0e2e9e833cb1872a4205c5b47568582805a3e98240f3fe2f16a5aaee6693d1e1589fd6918afce554b0 + checksum: 85dfb814cbb24cb00a52fc6232e0f0c2f4c359fabf44c52cef7938c39c059c1b0b2722895394b9a4e544a63fa7e3998fb8d8bacd2582ca1beb1197e93f55a16b languageName: node linkType: hard -"@aws-sdk/hash-node@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/hash-node@npm:3.226.0" +"@aws-sdk/hash-node@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/hash-node@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-buffer-from": 3.208.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: cbe466e2e3efdbb3aefe7772da734f6d00e0d1572c60e497b09460e055093b155c5e94bd3718135238bc05e58cb49abcdcd0fe5e34458bd3563b89d3d4a42251 + checksum: 26f8f2fca7ad13a1dc64753ee1ef85014eb89adfef9f500f5003e479807c5f2ec6ee185ae8e88d6bcb68e26512702fd6886fe211486531e4388e40fd003678a5 languageName: node linkType: hard -"@aws-sdk/hash-stream-node@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/hash-stream-node@npm:3.226.0" +"@aws-sdk/hash-stream-node@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/hash-stream-node@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: a6acb592e815fa48b39e7917599405ebf77c8c03e42ef039eea8886e0bda98c4d8a963506b137514787dca65cf4594cf756d49adcc67b0777b71f2ce7c4cd0da + checksum: 7aa9e69fb47c05f557fe79f382e20b99a87f9ada068a9458834afba550cdac13256d47baf42a50287aebe37e2f99de9747f80ea206c5da86e556855ec6b9d8bc languageName: node linkType: hard -"@aws-sdk/invalid-dependency@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/invalid-dependency@npm:3.226.0" +"@aws-sdk/invalid-dependency@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/invalid-dependency@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 4a6168b50675881442c9bc87e8f27e8317ece9251fbfd3d812d32edcd83f687328e6de518fa9f11b1bc984ad3a3454cd43b59c0362f04c03687ce5250ac5d720 + checksum: fe99f546cc041a9ccc8b29654fd3e8e466aef41697d4c69f4afc1aab1f1f83f2e7f0b9e0e20b3fe23843a01008902f00aeeb24cf26b7df0594c75a4ebf3bb3f3 languageName: node linkType: hard @@ -968,11 +957,11 @@ __metadata: linkType: hard "@aws-sdk/lib-storage@npm:^3.208.0": - version: 3.245.0 - resolution: "@aws-sdk/lib-storage@npm:3.245.0" + version: 3.261.0 + resolution: "@aws-sdk/lib-storage@npm:3.261.0" dependencies: - "@aws-sdk/middleware-endpoint": 3.226.0 - "@aws-sdk/smithy-client": 3.234.0 + "@aws-sdk/middleware-endpoint": 3.257.0 + "@aws-sdk/smithy-client": 3.261.0 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 @@ -980,267 +969,268 @@ __metadata: peerDependencies: "@aws-sdk/abort-controller": ^3.0.0 "@aws-sdk/client-s3": ^3.0.0 - checksum: 580221e5f577aad98a8b2ea362ec1c8198e8766ddc1503c4a0bb4afd2c96ad09b6cfc2d5aa252c7d0d3d8215a55bb39c65df1aceb525fb4f1118b4a1b801818d + checksum: 649d5ea5a9aa5723d2cfdecee9457a8b64662387b8a279e6a29a0c36e605c7b307b1666f76b3eb9422e27fc6235dcd506bfa0f0dbb00e2c6575346bf385a7d2e languageName: node linkType: hard -"@aws-sdk/md5-js@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/md5-js@npm:3.226.0" +"@aws-sdk/md5-js@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/md5-js@npm:3.258.0" dependencies: - "@aws-sdk/types": 3.226.0 - "@aws-sdk/util-utf8-browser": 3.188.0 - "@aws-sdk/util-utf8-node": 3.208.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 7d2dc4fefaf3136bf30e22f4645588624c8e2696b638357676f18df3ea1c11a7fd8dddc5b50cae739383590b2d3e10be02fd033c764c57c882b5a2230edb2d6f + checksum: e1812a1aae620d242d42b2425d40169e7af94c0a29275704d9dbb2ec68161207cc79a75cdc66b60b5ad24fd1607e6fcc14dc3aa3adb18fb71446b546898ea730 languageName: node linkType: hard -"@aws-sdk/middleware-bucket-endpoint@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.226.0" +"@aws-sdk/middleware-bucket-endpoint@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.259.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-arn-parser": 3.208.0 "@aws-sdk/util-config-provider": 3.208.0 tslib: ^2.3.1 - checksum: bb5e4a8bd79d578c103d216274a8175c42cea06c138338fa0854a30b8eab0c6a14d5996814f2ac9dcc82e1f137a240e657bb1e8841b52d8ade5c275771c43ca5 + checksum: 4ad5c0ece9723e52b70129f39737a66d8778eb538868af7dcbc574264f95d9705aa3a178c043c05861aac91487e76c3a663badce8022fa5aa9aa89622ca5f58a languageName: node linkType: hard -"@aws-sdk/middleware-content-length@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-content-length@npm:3.226.0" +"@aws-sdk/middleware-content-length@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-content-length@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 538b0222e2c8be61dc3090dfefe4b9ec1f0cbee155125edf5b654dbe36ab0b2d6befe3da6008194dc26bbf94d53b7e01edca683720061c4b43c6beb9dc278002 + checksum: 4f6129653b98185624c66bf2114417d492ec3cf91063da4cbce0e07ad3b1831766ff684491f0c14f92c8b9b39599a9781ca883f2d5ee42c3d38b273b6664f361 languageName: node linkType: hard -"@aws-sdk/middleware-endpoint@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-endpoint@npm:3.226.0" +"@aws-sdk/middleware-endpoint@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-endpoint@npm:3.257.0" dependencies: - "@aws-sdk/middleware-serde": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/signature-v4": 3.226.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/url-parser": 3.226.0 + "@aws-sdk/middleware-serde": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/signature-v4": 3.257.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/url-parser": 3.257.0 "@aws-sdk/util-config-provider": 3.208.0 - "@aws-sdk/util-middleware": 3.226.0 + "@aws-sdk/util-middleware": 3.257.0 tslib: ^2.3.1 - checksum: 22df6fd90e3b7d3edd58f427ebfbb229181ef190b2d795e0b400f70f95a573dc59666a08b26613db6bb1b764b13ba7ddec15fced2641e9678fad5500fca289be + checksum: e709f6b5dc6bee4659caa7740847f53be359b215d307210f093629f5013f3d0521e060ef6f7797c82dd02a9ac0528b47581e6e19fb0e2f38aa2ff3a8f1b9abc0 languageName: node linkType: hard -"@aws-sdk/middleware-expect-continue@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-expect-continue@npm:3.226.0" +"@aws-sdk/middleware-expect-continue@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-expect-continue@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 22924f008a7594cedde2c1f09b9b8ce005cf73bfcbf40330a2b783e42dffcd1fc88fd3a7b2b13da1ec4895c649f7605acea7b62dbbd3a45b00630b1cb9579bc4 + checksum: 911e087f822ce384f69a1f1d28449c99b81fa464af854f0a253656615104a047bcceb5a93837a9073a8466d2ec255550e5306a17c19087f5e3f060c27d1f930b languageName: node linkType: hard -"@aws-sdk/middleware-flexible-checksums@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.226.0" +"@aws-sdk/middleware-flexible-checksums@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.259.0" dependencies: - "@aws-crypto/crc32": 2.0.0 - "@aws-crypto/crc32c": 2.0.0 + "@aws-crypto/crc32": 3.0.0 + "@aws-crypto/crc32c": 3.0.0 "@aws-sdk/is-array-buffer": 3.201.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: c4f0531b3c917a0bfaf3b877f7f15de30f5e7e0a8366206c680efe4d0f60a0e54d7861ee14d213f713e157f164283d51724288b16fba67fef39d628324fef588 + checksum: b20e03676b38d8ba13b67c7bfe92b1802d8685fefd86934df472d51ec0ea856f470597e9cee98086b84bd6a8e8c02527c69961c9eac988e07a4bb805e5612e7b languageName: node linkType: hard -"@aws-sdk/middleware-host-header@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.226.0" +"@aws-sdk/middleware-host-header@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 35eb7d9f5eb2e45c58bb5887a12dc80f22e8fc630d53d356064c62ce3354c9054717697168ab3818f14c7baae3246480aa7251e6fcaf5c7104498df5dca9bbd6 + checksum: 426f6a6a9964ef993d4e7d8401162b62f758a7247872c6b58163d40ec8320738a84dbd2dbaccd008b24801642f6fd2d24b6af11331f00a204ed48e814f1e6e3c languageName: node linkType: hard -"@aws-sdk/middleware-location-constraint@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-location-constraint@npm:3.226.0" +"@aws-sdk/middleware-location-constraint@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-location-constraint@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 31db89d8935771aa73552fd99bc3a8fb3cca25c4e5bf978e96d05fd3aa8ab8403774ddeee08f83a4c9e5b4630082001e5d13aec1924353257fa87184dffba3e1 + checksum: 3894591a69b09987d6f4e9e85078167aff7fd836d819d0c06e2c5a0c191eb39e724ff3048280ba8763c02656cfbf06f4d9a47a602cc6e5c51ac50fec2127d16e languageName: node linkType: hard -"@aws-sdk/middleware-logger@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-logger@npm:3.226.0" +"@aws-sdk/middleware-logger@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-logger@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 7b7c2eb336f376f6e8c50ebd0fd9b6e9a749e21d6f5c433683a4e98edb311bb76fafc0bb0abfd75f61001466879be7d68aefb3958a332e540160a93ee9371b44 + checksum: 3b4ac39d4be50dde9b806500a50a6d2c4ab267f6e02e780fe70adf0d07f4026c09131e3f787d86833f4295987cbad6858839884d1c5f1ea56df729fc4a8d7d49 languageName: node linkType: hard -"@aws-sdk/middleware-recursion-detection@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.226.0" +"@aws-sdk/middleware-recursion-detection@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 194161d76a815df623c6699f7a7016268b4a01276baa3527682504001a4e2e948e2dd389d2065f62fe57509f20b9680ea907bfa52b861122335d276c9ab4ed61 + checksum: ce972140735fb040d00e1356409beac6dc5d9c477f975c73776de8294a91f81ac2a87e11c02581ff6c8b8c6f84e455e77a081291bbc536d22c9e128b07928fcd languageName: node linkType: hard -"@aws-sdk/middleware-retry@npm:3.235.0": - version: 3.235.0 - resolution: "@aws-sdk/middleware-retry@npm:3.235.0" +"@aws-sdk/middleware-retry@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/middleware-retry@npm:3.259.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/service-error-classification": 3.229.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/util-middleware": 3.226.0 - "@aws-sdk/util-retry": 3.229.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/service-error-classification": 3.257.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/util-middleware": 3.257.0 + "@aws-sdk/util-retry": 3.257.0 tslib: ^2.3.1 uuid: ^8.3.2 - checksum: 397226fd10d8b0587a35ccab92160223f10740beb01ccac75dda0e30336b83c091c9aa51b9132a56ff6cccd6353b9e3c6ecf21ae18f20f8127e7e9e209e59a2a + checksum: 22ae9d575cafbc9c3806a10871e2b6749d12b8109bc15e8eabe82e24613dc60196c2ab48df62fcf39e3dae33319146a58d3983c51a68c6c1da89e941ac2d4efa languageName: node linkType: hard -"@aws-sdk/middleware-sdk-s3@npm:3.231.0": - version: 3.231.0 - resolution: "@aws-sdk/middleware-sdk-s3@npm:3.231.0" +"@aws-sdk/middleware-sdk-s3@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-arn-parser": 3.208.0 tslib: ^2.3.1 - checksum: d60f189d7fb4bcbbd002999f537c49f22c1e2a3e5969702a8840f17d0314f6e9eb586681995bb2b6634ae5162bebf44a3ccfecf23fdfc3c9fa6797f9adc83423 + checksum: 67742b8c34552f1b69c7d4d7c58d68bf698203e094d399f7936959318daef47d060496f451babc727970942c9699c83b3a0b57d49da26812e70888a74d6ef585 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sqs@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.226.0" +"@aws-sdk/middleware-sdk-sqs@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-hex-encoding": 3.201.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 3c3d4cfaec156ad559a2409a095e7238e9fb6c1c6cb8b5304a62b61ea6b4241df907ea4ff0b71d0f0865b8338731113946e5df8cff361f73d2725730b2aa6db0 + checksum: 54cea36a767a3d7621eea7b22e59fb7268914228d3b26f6dbcd9cf17d9dc51a542c117249c992f5fd6e5804cdb04c675593ec150a41f564773b32ebf4c103b9b languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sts@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.226.0" +"@aws-sdk/middleware-sdk-sts@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-sdk-sts@npm:3.257.0" dependencies: - "@aws-sdk/middleware-signing": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/signature-v4": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/middleware-signing": 3.257.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/signature-v4": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 0b6e11889c9f1b5264eb38288dea5bd2987fa28338651939d005eaa0524f9cd41c570c545b34b08d25d858397b3f14a2b6a21238a8c88fc08719ed50b835cb15 + checksum: 9171f0fc8a9518b8344c58f26446c9b39a19d00b747f2ae02b92b022d8fdcdb65528f05e753999676b3c04bffa38d008a599d86c2e0fa65b2196cd9633ab4308 languageName: node linkType: hard -"@aws-sdk/middleware-serde@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-serde@npm:3.226.0" +"@aws-sdk/middleware-serde@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-serde@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: e8315079cc3ed4527d1434eb28becfaf951338d2ced21116753b52d3330eabbfd13f24382b3378bcc2c09ee0653a65e0d8353e9e32f512b69929908272b83fa2 + checksum: ceda3cb7bb7ceced0d5b69363dca51fa92b4f6defcd8299910eee0fe65d557871aa7777dade4abc64aa91347d038727fa65ff7ff0cc3d9716d0065dfd939c724 languageName: node linkType: hard -"@aws-sdk/middleware-signing@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-signing@npm:3.226.0" +"@aws-sdk/middleware-signing@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-signing@npm:3.257.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/signature-v4": 3.226.0 - "@aws-sdk/types": 3.226.0 - "@aws-sdk/util-middleware": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/signature-v4": 3.257.0 + "@aws-sdk/types": 3.257.0 + "@aws-sdk/util-middleware": 3.257.0 tslib: ^2.3.1 - checksum: 4f66483d359e21d1f7e56a1900f7271a561801e1ee4380deaa006ce750ce73245a5fe554d4c1ab60cf9ca127c41f35c53c0817c375df6f8f068c9ed7f9572444 + checksum: dfa31f59675427f7aff83852f24e2393bd7d1295421d68c2bb060faca001ce385d7a1d7231c92c48e841e58581ceeffef0209c7c91b51b19361af29120342a50 languageName: node linkType: hard -"@aws-sdk/middleware-ssec@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-ssec@npm:3.226.0" +"@aws-sdk/middleware-ssec@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-ssec@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: b85bf0e8be723a28a03dd7375284a5afc00edb04bf333a44286042768391243670b61b78361883d7c7890b118e0dc995219d7870227f845ac868a756e8a76a70 + checksum: 562d601a70f15446bf863d22427e8ee0949789a6cbebd2e82f5f513ff40e0da1f98c57f87677861e4347bad47e718388ea7cfd9478fb2ce47af14b89f7639aa9 languageName: node linkType: hard -"@aws-sdk/middleware-stack@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-stack@npm:3.226.0" +"@aws-sdk/middleware-stack@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-stack@npm:3.257.0" dependencies: tslib: ^2.3.1 - checksum: fd284bc28ee6ee576e3fe9dd3c2c9d64b8c95fa1bb213b5e41e23a57bbc2693652ee51028414eb278918235e591ef729db572b160bff963c6f74e7d6c15d33d0 + checksum: f7520d3e53d026f46c6504bcebef2a5732b724ab79079ccd2db0c052f6d4fd3cc4f06b951ff02723ef9ba46c6a0a0deca3282f152172ae7b1c3b2f493d35d584 languageName: node linkType: hard -"@aws-sdk/middleware-user-agent@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.226.0" +"@aws-sdk/middleware-user-agent@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/middleware-user-agent@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 8d3724aecd7b7f9f1a5b081263cb85864c969144105819f371a9675ee4f680c11e3b5ecbe181f57d2bfdde9c98b90267bd4afe0fc0822863041e0df52671f043 + checksum: b2fc45a734845d40d1e69bf7f0890613aad8357d4830f704c7ee6c1339ab51cbb0cef51920dc22718d29eb258fc1024f8c23cbc53a4f93b9b857f8bcacc442a1 languageName: node linkType: hard -"@aws-sdk/node-config-provider@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/node-config-provider@npm:3.226.0" +"@aws-sdk/node-config-provider@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/node-config-provider@npm:3.259.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 0e7c4c7ea20c5361c71f1ab0b99c19964f76c187659714cd6e87e1cc264d0ab29965d33618d9d47d373e3b108558cd6628fb36a00cdac614849e5044c6776213 + checksum: 72e4818b1ab641d1aa3b85c7901f7d64ad0399eb384cda1c875b41a37021c2be9e68021e6b0aa3f7298d2d46017259ee10356f07c314b4bc40146a44f355135a languageName: node linkType: hard -"@aws-sdk/node-http-handler@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/node-http-handler@npm:3.226.0" +"@aws-sdk/node-http-handler@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/node-http-handler@npm:3.257.0" dependencies: - "@aws-sdk/abort-controller": 3.226.0 - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/querystring-builder": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/abort-controller": 3.257.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/querystring-builder": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: e4080ec9f859be4b191416084fef8d2687f24d973169b8fef592a867c23c14fad74f4bea20f451b98fedfee6a265f2c89b0bee4fe7aabdb1fd05a7475bf12b91 + checksum: 37531827bc9e0b590c67ce57b87315fab8639a5feff1cb6cda8effdf6ac2d2fbc8a645765f004b52b03ff39c896da88a090b0dbcf5cfcf5d3d65d0b995f628fb languageName: node linkType: hard -"@aws-sdk/property-provider@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/property-provider@npm:3.226.0" +"@aws-sdk/property-provider@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/property-provider@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: d63c53313bb2797ab2ecfa2cff827b63417c0cc31abe8c666cd018a1d70da877b61ef1fb21e504d6408e72b20544756089938b44869b003ba3c313b39bca6d45 + checksum: 066290e9b88bcbc7d6bace37482ce955c782386a6cd75dc789efeb368bc87d0c410d01fd6b25bf66918e3328c6ffe1942aa643f4fdd4fa604feee36af9114894 languageName: node linkType: hard @@ -1254,13 +1244,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/protocol-http@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/protocol-http@npm:3.226.0" +"@aws-sdk/protocol-http@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/protocol-http@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 92cf35e1026a812c6c7ce8309fd685162ab7796237fc063e71dd9b292abf25902d6c0e02e93219101e1f506ef68a98f02eed6a61b18b8acd450ecb4bf8c1b467 + checksum: c51539e2f617d5d84e51ad9feeb93d51a310d808da18ceb53317aaf35af99bb8bea52eca532ab68d546b0ff5156b92cef5c3e98245f0b425795bd7910b608dad languageName: node linkType: hard @@ -1275,51 +1265,51 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/querystring-builder@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/querystring-builder@npm:3.226.0" +"@aws-sdk/querystring-builder@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/querystring-builder@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-uri-escape": 3.201.0 tslib: ^2.3.1 - checksum: 0014b8876d402787c56f606f66e79eb48ff100b01d7a657bb0766a7723ca184da0dd2aed405837e7e6c5781fd868d7a903eef25884b2d1881d30e2454f5c2bfc + checksum: a66b07cd1c4af544c7c6f903a735d1e8359f7d3b5c74803fc63b16b854eafec21f4b1c8874761edeebc4c2341f1f0b72190f03e0a005e8fff7b619e30cd59896 languageName: node linkType: hard -"@aws-sdk/querystring-parser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/querystring-parser@npm:3.226.0" +"@aws-sdk/querystring-parser@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/querystring-parser@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 13b23b4dff859d778a05f6874e318d95d6fbd79c62a06bb6f6dff8496ac2eaf86f60b17460c3595af854c2e316482c9fcc098655d475926039f7dff4a6f1ecf1 + checksum: cd391b7993a8e2397e3f0abd25e9b0b43747fe1b1415e9c5af6a3895567bb8dc9267d97e7d494c504f721b0b868bf9e0b93ec3677a5a7bc4ef2ff7252a402985 languageName: node linkType: hard -"@aws-sdk/service-error-classification@npm:3.229.0": - version: 3.229.0 - resolution: "@aws-sdk/service-error-classification@npm:3.229.0" - checksum: 7877963d62f4d43ce5116f0ddfd1b27cffab2b0e74a4ceb4006b1f85b17dd50eb9ae2f227cabf935261e42b7615d0a9de190dd684380c30e03dee6e9f7e12587 +"@aws-sdk/service-error-classification@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/service-error-classification@npm:3.257.0" + checksum: 231440f52a1c6c6d5ab62c13491736273fda49bb68bc278954dfaa3b7fa874946576c87a529504d6268472e646b3235cacb5c0fe5acc9af2398d87a56fabda3d languageName: node linkType: hard -"@aws-sdk/shared-ini-file-loader@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/shared-ini-file-loader@npm:3.226.0" +"@aws-sdk/shared-ini-file-loader@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/shared-ini-file-loader@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 7b43e4d70f33b1098c9582a20dd5cf11c0e2efe5e7f4f854ee1fdfe2f804a7171deeb76f167c46ef7365bb584e29c816d58b6d8f6c9ac9debb124cccf59ebf59 + checksum: 27738db81e2b9c8e0bd248e1c0ed7f21b65b52204b247cb8119b3b48b55844c2450e5fe20bb1193311177a8a18e8bb99594d3bfde71dacd1ee9ed8bbad9a915b languageName: node linkType: hard -"@aws-sdk/signature-v4-multi-region@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/signature-v4-multi-region@npm:3.226.0" +"@aws-sdk/signature-v4-multi-region@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/signature-v4-multi-region@npm:3.257.0" dependencies: - "@aws-sdk/protocol-http": 3.226.0 - "@aws-sdk/signature-v4": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/protocol-http": 3.257.0 + "@aws-sdk/signature-v4": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-arn-parser": 3.208.0 tslib: ^2.3.1 peerDependencies: @@ -1327,45 +1317,46 @@ __metadata: peerDependenciesMeta: "@aws-sdk/signature-v4-crt": optional: true - checksum: 173645989956907bbd83c4098e2e52f977272073713ac894ec7bf74f84ddb071c2142b2f5edfb7f7f939a60b8d8b5140bd114e6b028bb5216c341da7eb910ea2 + checksum: 260d37db48e90addbaa302358a98307c8c61561953e37986f6f4571258784decf3e582f9da3c8cc4d545b3ddc63592e983949890e6204872469f7c837b3bb939 languageName: node linkType: hard -"@aws-sdk/signature-v4@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/signature-v4@npm:3.226.0" +"@aws-sdk/signature-v4@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/signature-v4@npm:3.257.0" dependencies: "@aws-sdk/is-array-buffer": 3.201.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-hex-encoding": 3.201.0 - "@aws-sdk/util-middleware": 3.226.0 + "@aws-sdk/util-middleware": 3.257.0 "@aws-sdk/util-uri-escape": 3.201.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 8bc6ea1ad467d59f1ff6c5b814277e16d0d5b2d1455f21969b4575f572fdc013284e356e0f24436c89c8b99a51d0e384b01daa2bace1c3d69e28f35a23ef9802 + checksum: 6faf6a3d8f51603240f6375b76bfd031223aa5cf1f0385cfa97833e6b188fb9b746caab53a45d0e7a311ca9735c82b56c67aed68b1fbcdf4bbcbf93e288fd09f languageName: node linkType: hard -"@aws-sdk/smithy-client@npm:3.234.0": - version: 3.234.0 - resolution: "@aws-sdk/smithy-client@npm:3.234.0" +"@aws-sdk/smithy-client@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/smithy-client@npm:3.261.0" dependencies: - "@aws-sdk/middleware-stack": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/middleware-stack": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 7b8299f81fde410b8f597662d4174a29740cb2791a2377e5009a73c0e7531fb440712ab25c837a0351dbceac4763cc8fadc6d4362727cf3ae749b25515da4ea1 + checksum: 1394ce351d52bc3bd17b484acbfb9171a57203b64741a21d1f8c9d89443f165186539194d463ccdd2dfad18a981ff9561088d2d2c52e0467d8225400312b5486 languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/token-providers@npm:3.245.0" +"@aws-sdk/token-providers@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/token-providers@npm:3.261.0" dependencies: - "@aws-sdk/client-sso-oidc": 3.245.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/shared-ini-file-loader": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/client-sso-oidc": 3.261.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/shared-ini-file-loader": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 900a73b999c50eb35b3eda594210448329f5068b57a2d8d57ee8e4f3d960116ece36952ca1fbe43b5e8e9119927de916033f73ff969bae3a8394d4ef98f1d0c7 + checksum: ca65f92443726c14860cd4adc7fde0f6eb073cdfa93d27d05495dbede3b6ead9157ad4dc5471398f47b3202527cfaf0e44f0d184d6a4be7a0290e9ae0bd9b9ab languageName: node linkType: hard @@ -1376,23 +1367,23 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/types@npm:3.226.0, @aws-sdk/types@npm:^3.1.0, @aws-sdk/types@npm:^3.110.0, @aws-sdk/types@npm:^3.208.0": - version: 3.226.0 - resolution: "@aws-sdk/types@npm:3.226.0" +"@aws-sdk/types@npm:3.257.0, @aws-sdk/types@npm:^3.208.0, @aws-sdk/types@npm:^3.222.0": + version: 3.257.0 + resolution: "@aws-sdk/types@npm:3.257.0" dependencies: tslib: ^2.3.1 - checksum: 0041a8c0924ec7ba4ff787ae329a80b3edb9ace43e38fe3656a1862ae5324427fb09836275c0962cbc80e3c34a6ee512a108a5c4e7997f29664e3e8930cffd80 + checksum: eab2154f7d27d0bec29df41374481652525e1658ad987c64ed02cbe7b7388c563e6a8d317c8fc564ac6fbd97c98be700a29352c9acebc3903cf3305431bf0a86 languageName: node linkType: hard -"@aws-sdk/url-parser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/url-parser@npm:3.226.0" +"@aws-sdk/url-parser@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/url-parser@npm:3.257.0" dependencies: - "@aws-sdk/querystring-parser": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/querystring-parser": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: cb8d4b13c0de7336728a7a60a246108c0ecd46e5e493cb1006f5ab58c5dbae0ac36a791536786b1facc90f58a8d6decca9f4fda2cba19667ba5a9f5f4fcadb63 + checksum: 3b781c7fe94572e673e0651a47806cf023f60fb1268d2abbad9364c70112b1ad37d2261f631e0d7ce5c5ec543faa7e316d987e519091db68bf121384ad557043 languageName: node linkType: hard @@ -1452,39 +1443,39 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-browser@npm:3.234.0": - version: 3.234.0 - resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.234.0" +"@aws-sdk/util-defaults-mode-browser@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/util-defaults-mode-browser@npm:3.261.0" dependencies: - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 bowser: ^2.11.0 tslib: ^2.3.1 - checksum: 79a381a632f867477dc7f948243c8ba82932d3f10325c76a5f2cf96412560648d149ba43ee31794bc45d81158a8c361d890b291880fc0c05f9bafc99cded5ef4 + checksum: 218c97dc362549796a318048d496f8e105d023dd040ecf811c1cab8bc807c80afb43b8cae8bb6ac3c87f5bdfe07f9248fccd825554287cb5c39f84dddcb521b1 languageName: node linkType: hard -"@aws-sdk/util-defaults-mode-node@npm:3.234.0": - version: 3.234.0 - resolution: "@aws-sdk/util-defaults-mode-node@npm:3.234.0" +"@aws-sdk/util-defaults-mode-node@npm:3.261.0": + version: 3.261.0 + resolution: "@aws-sdk/util-defaults-mode-node@npm:3.261.0" dependencies: - "@aws-sdk/config-resolver": 3.234.0 - "@aws-sdk/credential-provider-imds": 3.226.0 - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/property-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/config-resolver": 3.259.0 + "@aws-sdk/credential-provider-imds": 3.259.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/property-provider": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: b70becd9e561c1622c75a452ed8c7a8b14b84eba35988159f29476db8c2b47ec72f0b7c19d1a252c725756af1fff1df4201e5e92b6136d1df9170e806dca5219 + checksum: d784ae1aaf51640b0b591028b91522c8c6dc58558245c6dfcd253adbfcc42e2496d4f8139df47b8b9932edd5eccbcdf8829a5d0adcf91b634ff8a506934d4399 languageName: node linkType: hard -"@aws-sdk/util-endpoints@npm:3.245.0": - version: 3.245.0 - resolution: "@aws-sdk/util-endpoints@npm:3.245.0" +"@aws-sdk/util-endpoints@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-endpoints@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: 22783fb178e8901385b20b0d19b944ad41297cc19f0561ac1722e86757ca6910fd3766626a0493372f718a0726bef920a5b39cc41fdceb1012f14e833541041b + checksum: ba1aec13c8ceb9519400f2c77db1743b34dec4380b27598a8862e94c9df43e3e8b4e183f230fb6bdaaeb89653d232e6a13dcc2016c6a9d12246f58b630fd3ec0 languageName: node linkType: hard @@ -1506,48 +1497,48 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-middleware@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-middleware@npm:3.226.0" +"@aws-sdk/util-middleware@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-middleware@npm:3.257.0" dependencies: tslib: ^2.3.1 - checksum: 51a4ba9a784943b723a2c57bbb889a4bc743f0f1219000ef73512e259069d63c3baa805aa375277c9d904da23301d0389bc0bd525b0b55274d7658fb62173e55 + checksum: 77ac007288fa98ec55c10af5a097f7f829d7ec53b6eecc43bc00a18b9ea011194aec42fb69e58421f87363490cef89b811330eaf174739fdf6b810b40cd46768 languageName: node linkType: hard -"@aws-sdk/util-retry@npm:3.229.0": - version: 3.229.0 - resolution: "@aws-sdk/util-retry@npm:3.229.0" +"@aws-sdk/util-retry@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-retry@npm:3.257.0" dependencies: - "@aws-sdk/service-error-classification": 3.229.0 + "@aws-sdk/service-error-classification": 3.257.0 tslib: ^2.3.1 - checksum: e4ab435000abfa1dc21153682ce684302bd6e69d48b7d2c876ff8dfa66793a43223961a3755d05abb1f94f82765eac2b9d48e55c688a957a7f6b5d032bbc46ee + checksum: 7d7054c5a73f3acaf59b620386ad0a6226ec6b2761e5c59f304694f8a7f5cb8ab0eb7d51be102e81d6e2a5ec97b20bd8814cf245ff44fcc5587d4e5b80a3b892 languageName: node linkType: hard -"@aws-sdk/util-stream-browser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-stream-browser@npm:3.226.0" +"@aws-sdk/util-stream-browser@npm:3.258.0": + version: 3.258.0 + resolution: "@aws-sdk/util-stream-browser@npm:3.258.0" dependencies: - "@aws-sdk/fetch-http-handler": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/fetch-http-handler": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-base64": 3.208.0 "@aws-sdk/util-hex-encoding": 3.201.0 - "@aws-sdk/util-utf8-browser": 3.188.0 + "@aws-sdk/util-utf8": 3.254.0 tslib: ^2.3.1 - checksum: 7e232bf20733618b25f1dfee93d53a397cf22bdc7191e920b649837773fc6e551c1671f71581d6294d9e77c4b00dabb7baa182e85cedad470642e743a5b05a5c + checksum: c3a99e5d5fd2e6c7aff63bc7041d1f49a5a328071421aa050ee57bdeeceb5e34005f4895df5fd2e358e245ca513c67717a896d8f2402b431d41bc22abe6b135b languageName: node linkType: hard -"@aws-sdk/util-stream-node@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-stream-node@npm:3.226.0" +"@aws-sdk/util-stream-node@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-stream-node@npm:3.257.0" dependencies: - "@aws-sdk/node-http-handler": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/node-http-handler": 3.257.0 + "@aws-sdk/types": 3.257.0 "@aws-sdk/util-buffer-from": 3.208.0 tslib: ^2.3.1 - checksum: 91ed91380582bb1989d7420d4939af240fcaf0805845a308ebb9917a1b5da3cae23ebcc9963fcd20c362467130951fc13666e181eb8d40da42f213eaebcada00 + checksum: d2773a857f8400aaef45237dff4f454b233eeed2644739f1dbd90f88ef02dfdfbc456ee6b92fb13b9fea6c29d0e5853f9eb942407487f51528128ed23f5a04a7 languageName: node linkType: hard @@ -1565,30 +1556,30 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.226.0" +"@aws-sdk/util-user-agent-browser@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.257.0" dependencies: - "@aws-sdk/types": 3.226.0 + "@aws-sdk/types": 3.257.0 bowser: ^2.11.0 tslib: ^2.3.1 - checksum: b89b63e03636b98ccb811e713776c8ee5ce92a280edfd429e418dc69bb55b770b47d6118419be76207afe137f293fdb2e87605922714189df8ddbd4573185717 + checksum: f475d6096ff92ba2292de6cc78e2e1512df96c7fff3d8ef39148884533c14cc341a84ce3c4969f78cca2d8d4098c4cefefd72edf7cb480c33f8597f5828245c3 languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.226.0" +"@aws-sdk/util-user-agent-node@npm:3.259.0": + version: 3.259.0 + resolution: "@aws-sdk/util-user-agent-node@npm:3.259.0" dependencies: - "@aws-sdk/node-config-provider": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/node-config-provider": 3.259.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 peerDependencies: aws-crt: ">=1.0.0" peerDependenciesMeta: aws-crt: optional: true - checksum: a3b620fa13e5e61bc874d777d451ec522f659f933b7d7f7642c10fbb12ce13dd068c2b5370fd6132cca5ddcd22243fb04b4e926a4dd8aedeb08270a9bb49ee74 + checksum: ed2ae75ef0ccd5f58f16887c8cfd521006e8efaa8431420d1b55c3f885c501bbb06e6a4f262c0239a88fbec9100923cd277b4539838df9fe9f391c411c5767ee languageName: node linkType: hard @@ -1601,24 +1592,24 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-utf8-node@npm:3.208.0": - version: 3.208.0 - resolution: "@aws-sdk/util-utf8-node@npm:3.208.0" +"@aws-sdk/util-utf8@npm:3.254.0": + version: 3.254.0 + resolution: "@aws-sdk/util-utf8@npm:3.254.0" dependencies: "@aws-sdk/util-buffer-from": 3.208.0 tslib: ^2.3.1 - checksum: 0f4c1d0d3f6eb40d92bc7163c6dcf97f90b3a8be05df46ba4f9bb7723a3e6acabf2cb0f2486411b03d22e8fcccae9e757ed02afad384ff5f44a3a659a78c5752 + checksum: e5dfe7565f2de32245a544d1d715d803025bc5522538c0206fa61377f747804d95fc2e5e25976144bb63a6857e360b4286d101e730ab5d39866c60383a47e7d5 languageName: node linkType: hard -"@aws-sdk/util-waiter@npm:3.226.0": - version: 3.226.0 - resolution: "@aws-sdk/util-waiter@npm:3.226.0" +"@aws-sdk/util-waiter@npm:3.257.0": + version: 3.257.0 + resolution: "@aws-sdk/util-waiter@npm:3.257.0" dependencies: - "@aws-sdk/abort-controller": 3.226.0 - "@aws-sdk/types": 3.226.0 + "@aws-sdk/abort-controller": 3.257.0 + "@aws-sdk/types": 3.257.0 tslib: ^2.3.1 - checksum: d182033937bd5ab024598a48ad28030267c1b9aa54175f24d0e57ea87975a0a07b5da7d0e5f43efb663e908a5df591dfa307bf9707a02d84eb49b089e9c5a5db + checksum: 4dd7310ca0b9cdda7c55e3e4a80c7b0b323961ea238cc3ab512e78495d356840ddd5eb0b99add4baf1abf19759ab9ab6bb5d528fe86b61193e0e4f3a854c223b languageName: node linkType: hard @@ -3307,12 +3298,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.20.7 - resolution: "@babel/runtime@npm:7.20.7" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.14.6, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.20.13 + resolution: "@babel/runtime@npm:7.20.13" dependencies: regenerator-runtime: ^0.13.11 - checksum: 4629ce5c46f06cca9cfb9b7fc00d48003335a809888e2b91ec2069a2dcfbfef738480cff32ba81e0b7c290f8918e5c22ddcf2b710001464ee84ba62c7e32a3a3 + checksum: 09b7a97a05c80540db6c9e4ddf8c5d2ebb06cae5caf3a87e33c33f27f8c4d49d9c67a2d72f1570e796045288fad569f98a26ceba0c4f5fad2af84b6ad855c4fb languageName: node linkType: hard @@ -3432,6 +3423,7 @@ __metadata: resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: "@backstage/backend-app-api": "workspace:^" + "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" @@ -3528,6 +3520,14 @@ __metadata: languageName: unknown linkType: soft +"@backstage/backend-dev-utils@workspace:^, @backstage/backend-dev-utils@workspace:packages/backend-dev-utils": + version: 0.0.0-use.local + resolution: "@backstage/backend-dev-utils@workspace:packages/backend-dev-utils" + dependencies: + "@backstage/cli": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/backend-plugin-api@workspace:^, @backstage/backend-plugin-api@workspace:packages/backend-plugin-api": version: 0.0.0-use.local resolution: "@backstage/backend-plugin-api@workspace:packages/backend-plugin-api" @@ -3669,10 +3669,12 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/eslint-plugin": "workspace:^" "@backstage/release-manifests": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" + "@esbuild-kit/cjs-loader": ^2.4.1 "@manypkg/get-packages": ^1.1.3 "@octokit/request": ^6.0.0 "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 @@ -3691,6 +3693,7 @@ __metadata: "@swc/core": ^1.3.9 "@swc/helpers": ^0.4.7 "@swc/jest": ^0.2.22 + "@types/cross-spawn": ^6.0.2 "@types/diff": ^5.0.0 "@types/express": ^4.17.6 "@types/fs-extra": ^9.0.1 @@ -3718,6 +3721,7 @@ __metadata: chalk: ^4.0.0 chokidar: ^3.3.1 commander: ^9.1.0 + cross-spawn: ^7.0.3 css-loader: ^6.5.1 del: ^6.0.0 diff: ^5.0.0 @@ -3730,7 +3734,6 @@ __metadata: eslint-plugin-import: ^2.25.4 eslint-plugin-jest: ^27.0.0 eslint-plugin-jsx-a11y: ^6.5.1 - eslint-plugin-monorepo: ^0.3.2 eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 eslint-webpack-plugin: ^3.1.1 @@ -3887,7 +3890,57 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-components@^0.12.0, @backstage/core-components@^0.12.3, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": +"@backstage/core-components@npm:^0.12.0, @backstage/core-components@npm:^0.12.3": + version: 0.12.3 + resolution: "@backstage/core-components@npm:0.12.3" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/core-plugin-api": ^1.3.0 + "@backstage/errors": ^1.1.4 + "@backstage/theme": ^0.2.16 + "@backstage/version-bridge": ^1.0.3 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@react-hookz/web": ^20.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + history: ^5.0.0 + immer: ^9.0.1 + lodash: ^4.17.21 + pluralize: ^8.0.0 + prop-types: ^15.7.2 + qs: ^6.9.4 + rc-progress: 3.4.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.6 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ~3.18.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: f9c242af07b500f0de738591848776ad3864fb52e30f1979e547d6d607a0eb96df5c1464c8dadb4f5c1d7dd6c10ae74e4c2f60eba5380b704f4b01ac6711131c + languageName: node + linkType: hard + +"@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: @@ -4054,6 +4107,17 @@ __metadata: languageName: unknown linkType: soft +"@backstage/eslint-plugin@workspace:^, @backstage/eslint-plugin@workspace:packages/eslint-plugin": + version: 0.0.0-use.local + resolution: "@backstage/eslint-plugin@workspace:packages/eslint-plugin" + dependencies: + "@backstage/cli": "workspace:^" + "@manypkg/get-packages": ^1.1.3 + eslint: ^8.33.0 + minimatch: ^5.1.2 + languageName: unknown + linkType: soft + "@backstage/integration-aws-node@workspace:^, @backstage/integration-aws-node@workspace:packages/integration-aws-node": version: 0.0.0-use.local resolution: "@backstage/integration-aws-node@workspace:packages/integration-aws-node" @@ -4073,7 +4137,26 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@^1.1.9, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@npm:^1.1.9": + version: 1.1.9 + resolution: "@backstage/integration-react@npm:1.1.9" + dependencies: + "@backstage/config": ^1.0.6 + "@backstage/core-components": ^0.12.3 + "@backstage/core-plugin-api": ^1.3.0 + "@backstage/integration": ^1.4.2 + "@backstage/theme": ^0.2.16 + "@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 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + checksum: 28d94f05e65944308ac6b0709e22336e6e745fe6143f7c3851ccf200725066fc73f53d238e559599d003818c764a86645e3d3f3178e2e5fd0d7cc968d7cc6375 + languageName: node + linkType: hard + +"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4190,6 +4273,7 @@ __metadata: react-use: ^17.2.4 remark-gfm: ^3.0.1 peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 react: ^16.13.1 || ^17.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown @@ -4344,7 +4428,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-api-docs@workspace:plugins/api-docs" dependencies: - "@asyncapi/react-component": 1.0.0-next.44 + "@asyncapi/react-component": 1.0.0-next.47 "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" @@ -4390,7 +4474,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -4701,6 +4785,7 @@ __metadata: resolution: "@backstage/plugin-bazaar-backend@workspace:plugins/bazaar-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -5438,7 +5523,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@date-io/luxon": ^1.3.13 - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@material-ui/pickers": ^3.3.10 @@ -5629,7 +5714,7 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.10 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -5743,7 +5828,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -5759,6 +5844,44 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-entity-validation@workspace:plugins/entity-validation": + version: 0.0.0-use.local + resolution: "@backstage/plugin-entity-validation@workspace:plugins/entity-validation" + dependencies: + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@codemirror/language": ^6.0.0 + "@codemirror/legacy-modes": ^6.1.0 + "@codemirror/view": ^6.0.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@react-hookz/web": ^20.0.0 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + "@uiw/react-codemirror": ^4.9.3 + cross-fetch: ^3.1.5 + lodash: ^4.17.21 + msw: ^0.49.0 + react-use: ^17.2.4 + yaml: ^2.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-events-backend-module-aws-sqs@workspace:plugins/events-backend-module-aws-sqs": version: 0.0.0-use.local resolution: "@backstage/plugin-events-backend-module-aws-sqs@workspace:plugins/events-backend-module-aws-sqs" @@ -6382,6 +6505,33 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager": + version: 0.0.0-use.local + resolution: "@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + graphql-voyager: ^1.0.0-rc.31 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-home@npm:^0.4.30": version: 0.4.30 resolution: "@backstage/plugin-home@npm:0.4.30" @@ -6545,6 +6695,7 @@ __metadata: resolution: "@backstage/plugin-kafka-backend@workspace:plugins/kafka-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -6686,6 +6837,31 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-lighthouse-backend@workspace:^, @backstage/plugin-lighthouse-backend@workspace:plugins/lighthouse-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-lighthouse-backend@workspace:plugins/lighthouse-backend" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-tasks": "workspace:^" + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-lighthouse-common": "workspace:^" + "@backstage/types": "workspace:^" + winston: ^3.2.1 + languageName: unknown + linkType: soft + +"@backstage/plugin-lighthouse-common@workspace:^, @backstage/plugin-lighthouse-common@workspace:plugins/lighthouse-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-lighthouse-common@workspace:plugins/lighthouse-common" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/plugin-lighthouse@workspace:^, @backstage/plugin-lighthouse@workspace:plugins/lighthouse": version: 0.0.0-use.local resolution: "@backstage/plugin-lighthouse@workspace:plugins/lighthouse" @@ -6698,6 +6874,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/plugin-lighthouse-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 @@ -6718,6 +6895,39 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-microsoft-calendar@workspace:^, @backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar": + version: 0.0.0-use.local + resolution: "@backstage/plugin-microsoft-calendar@workspace:plugins/microsoft-calendar" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@microsoft/microsoft-graph-types": ^2.25.0 + "@tanstack/react-query": ^4.1.3 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/user-event": ^14.0.0 + "@types/node": ^16.11.26 + classnames: ^2.3.1 + cross-fetch: ^3.1.5 + dompurify: ^2.3.6 + lodash: ^4.17.21 + luxon: ^3.0.0 + material-ui-popup-state: ^1.9.3 + msw: ^0.49.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-newrelic-dashboard@workspace:^, @backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard": version: 0.0.0-use.local resolution: "@backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard" @@ -6781,7 +6991,7 @@ __metadata: "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -6867,6 +7077,7 @@ __metadata: resolution: "@backstage/plugin-periskop-backend@workspace:plugins/periskop-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@types/express": "*" @@ -7056,7 +7267,7 @@ __metadata: "@backstage/plugin-search-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -7082,6 +7293,7 @@ __metadata: resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@types/express": ^4.17.6 @@ -7349,11 +7561,11 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@rjsf/core": ^3.2.1 - "@rjsf/core-v5": "npm:@rjsf/core@5.0.1" + "@rjsf/core-v5": "npm:@rjsf/core@5.1.0" "@rjsf/material-ui": ^3.2.1 - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.0.1" - "@rjsf/utils": 5.0.1 - "@rjsf/validator-ajv8": 5.0.1 + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.1.0" + "@rjsf/utils": 5.1.0 + "@rjsf/validator-ajv8": 5.1.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 @@ -7408,7 +7620,7 @@ __metadata: "@react-hookz/web": ^20.0.0 "@rjsf/core": ^3.2.1 "@rjsf/material-ui": ^3.2.1 - "@rjsf/utils": 5.0.1 + "@rjsf/utils": 5.1.0 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 @@ -7540,7 +7752,31 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-react@^1.4.0, @backstage/plugin-search-react@workspace:^, @backstage/plugin-search-react@workspace:plugins/search-react": +"@backstage/plugin-search-react@npm:^1.4.0": + version: 1.4.0 + resolution: "@backstage/plugin-search-react@npm:1.4.0" + dependencies: + "@backstage/core-components": ^0.12.3 + "@backstage/core-plugin-api": ^1.3.0 + "@backstage/plugin-search-common": ^1.2.1 + "@backstage/theme": ^0.2.16 + "@backstage/types": ^1.0.2 + "@backstage/version-bridge": ^1.0.3 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + lodash: ^4.17.21 + qs: ^6.9.4 + react-use: ^17.3.2 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 0fe18ee991bea12ba4b525b1ed4934f53a2cb2172851762c67d844405206ef8ed335ce8ad6412b4c4f133ae2b1f654b5086cf9997521e2e2cb2ef9cad6891e0a + languageName: node + linkType: hard + +"@backstage/plugin-search-react@workspace:^, @backstage/plugin-search-react@workspace:plugins/search-react": version: 0.0.0-use.local resolution: "@backstage/plugin-search-react@workspace:plugins/search-react" dependencies: @@ -8004,7 +8240,7 @@ __metadata: "@backstage/plugin-techdocs-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@testing-library/jest-dom": ^5.10.1 @@ -8071,7 +8307,7 @@ __metadata: "@backstage/plugin-techdocs-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.9.13 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 "@react-hookz/web": ^20.0.0 @@ -8083,6 +8319,7 @@ __metadata: cross-fetch: ^3.1.5 git-url-parse: ^13.0.0 msw: ^0.49.0 + photoswipe: ^5.3.5 react-use: ^17.2.4 peerDependencies: react: ^16.13.1 || ^17.0.0 @@ -8268,6 +8505,7 @@ __metadata: resolution: "@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" @@ -8800,8 +9038,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.3.2 - resolution: "@codemirror/language@npm:6.3.2" + version: 6.4.0 + resolution: "@codemirror/language@npm:6.4.0" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 @@ -8809,7 +9047,7 @@ __metadata: "@lezer/highlight": ^1.0.0 "@lezer/lr": ^1.0.0 style-mod: ^4.0.0 - checksum: b70ed9b85d0bea79181c86e88a1f5c0bada30680ee1fe6a68efc01bc037c3d14f94a83602fc46cc4b4393589605ef7e986ed5174443502f3365dd61f883894fa + checksum: 607072e234db59a9a21eb41b8777b62d68a55ed28298edc4f6aaedfcf52349db1fe3ff3e7747ccfc77f03757bad45ba9a657d59a0e9c67be1231902586dec7a3 languageName: node linkType: hard @@ -8864,13 +9102,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.7.2 - resolution: "@codemirror/view@npm:6.7.2" + version: 6.7.3 + resolution: "@codemirror/view@npm:6.7.3" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.0.0 w3c-keyname: ^2.2.4 - checksum: ad08a4a0a50e2b34c0141311e7db9f045a2186b81ae28271318374b5b9964435267ec0af210b5d061cb84bc8fdca6dabc1919eb7fe05837d931038b9095c3f8c + checksum: 37c0458cf45e52a1af9b9bef29108dd84bb91c6818ecad432d89627039d92f6b234b033cf14ecbc1c5b533694127478942fcc9641fdf52b9a1b20eccc018e27c languageName: node linkType: hard @@ -9045,9 +9283,29 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-arm64@npm:0.17.5" +"@esbuild-kit/cjs-loader@npm:^2.4.1": + version: 2.4.2 + resolution: "@esbuild-kit/cjs-loader@npm:2.4.2" + dependencies: + "@esbuild-kit/core-utils": ^3.0.0 + get-tsconfig: ^4.4.0 + checksum: e346e339bfc7eff5c52c270fd0ec06a7f2341b624adfb69f84b7d83f119c35070420906f2761a0b4604e0a0ec90e35eaf12544585476c428ed6d6ee3b250c0fe + languageName: node + linkType: hard + +"@esbuild-kit/core-utils@npm:^3.0.0": + version: 3.0.0 + resolution: "@esbuild-kit/core-utils@npm:3.0.0" + dependencies: + esbuild: ~0.15.10 + source-map-support: ^0.5.21 + checksum: 0e89ec718e2211bf95c48a8085aaef88e8e416f42abd1c62d488d5458eecd3fbc144179a0c5570ad36fa7e2d3bbc411f8d3fb28802c37ced2154dc2c6ded9dfe + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-arm64@npm:0.17.6" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -9059,65 +9317,65 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-arm@npm:0.17.5" +"@esbuild/android-arm@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-arm@npm:0.17.6" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/android-x64@npm:0.17.5" +"@esbuild/android-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/android-x64@npm:0.17.6" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/darwin-arm64@npm:0.17.5" +"@esbuild/darwin-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/darwin-arm64@npm:0.17.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/darwin-x64@npm:0.17.5" +"@esbuild/darwin-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/darwin-x64@npm:0.17.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/freebsd-arm64@npm:0.17.5" +"@esbuild/freebsd-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/freebsd-arm64@npm:0.17.6" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/freebsd-x64@npm:0.17.5" +"@esbuild/freebsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/freebsd-x64@npm:0.17.6" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-arm64@npm:0.17.5" +"@esbuild/linux-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-arm64@npm:0.17.6" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-arm@npm:0.17.5" +"@esbuild/linux-arm@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-arm@npm:0.17.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-ia32@npm:0.17.5" +"@esbuild/linux-ia32@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-ia32@npm:0.17.6" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -9129,86 +9387,86 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-loong64@npm:0.17.5" +"@esbuild/linux-loong64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-loong64@npm:0.17.6" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-mips64el@npm:0.17.5" +"@esbuild/linux-mips64el@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-mips64el@npm:0.17.6" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-ppc64@npm:0.17.5" +"@esbuild/linux-ppc64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-ppc64@npm:0.17.6" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-riscv64@npm:0.17.5" +"@esbuild/linux-riscv64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-riscv64@npm:0.17.6" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-s390x@npm:0.17.5" +"@esbuild/linux-s390x@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-s390x@npm:0.17.6" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/linux-x64@npm:0.17.5" +"@esbuild/linux-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/linux-x64@npm:0.17.6" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/netbsd-x64@npm:0.17.5" +"@esbuild/netbsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/netbsd-x64@npm:0.17.6" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/openbsd-x64@npm:0.17.5" +"@esbuild/openbsd-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/openbsd-x64@npm:0.17.6" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/sunos-x64@npm:0.17.5" +"@esbuild/sunos-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/sunos-x64@npm:0.17.6" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-arm64@npm:0.17.5" +"@esbuild/win32-arm64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-arm64@npm:0.17.6" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-ia32@npm:0.17.5" +"@esbuild/win32-ia32@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-ia32@npm:0.17.6" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.5": - version: 0.17.5 - resolution: "@esbuild/win32-x64@npm:0.17.5" +"@esbuild/win32-x64@npm:0.17.6": + version: 0.17.6 + resolution: "@esbuild/win32-x64@npm:0.17.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -9230,6 +9488,56 @@ __metadata: languageName: node linkType: hard +"@f/animate@npm:^1.0.1": + version: 1.0.1 + resolution: "@f/animate@npm:1.0.1" + dependencies: + "@f/elapsed-time": ^1.0.0 + "@f/raf": ^1.0.0 + "@f/tween": ^1.0.0 + checksum: 660b44d297b1a6e5e28c48438633e00ded40f8e51adb4bfb26fc809b60c8c056f567f2e61f4f842c8fd2cf8a85dffaa1c2502bd0963eb926135f2d66d9f997db + languageName: node + linkType: hard + +"@f/elapsed-time@npm:^1.0.0": + version: 1.0.0 + resolution: "@f/elapsed-time@npm:1.0.0" + dependencies: + "@f/timestamp": ^1.0.0 + checksum: 5934d24a667bae4e0089408aa362c0ee1503945adf73ca0ff0d09fed33d62d070f0323eb9a54f42c37bd0545330a0f63da13319f66cc89fef59b8917a3278b5f + languageName: node + linkType: hard + +"@f/map-obj@npm:^1.2.2": + version: 1.2.2 + resolution: "@f/map-obj@npm:1.2.2" + checksum: d67db6074e1daa7a3c0f8c2e54094bff48b54d11817fddc886631dd8a17586d0040e7116282a374cc1d3d643d05862d49a1062ea5b2d03b9069507c09ae888a4 + languageName: node + linkType: hard + +"@f/raf@npm:^1.0.0": + version: 1.0.3 + resolution: "@f/raf@npm:1.0.3" + checksum: 800344caf4c649c0bcdefd4febbf3f0eed96bb9b7e54b5bc6eebd7d781c9e6d98ba22fb39da41474080d97ac21916bd1e82051558b43dabcbbf410d2dd0899c1 + languageName: node + linkType: hard + +"@f/timestamp@npm:^1.0.0": + version: 1.0.0 + resolution: "@f/timestamp@npm:1.0.0" + checksum: 8c37acb40cf67952309a214be2ddfd5c4f6634a414efc47406e8d1c1624e74662f584f6b48f3382c742f256aea1537e730e74c6078e52be3a28d0624cc7306a0 + languageName: node + linkType: hard + +"@f/tween@npm:^1.0.0": + version: 1.0.1 + resolution: "@f/tween@npm:1.0.1" + dependencies: + "@f/map-obj": ^1.2.2 + checksum: e37155c43875becc9eca8425b8dc83e64a78fa327738b33fcb3946418369568aa77007ade39591991379187381da829702e5cb84729dd2a0bc3bb4b7c94e4f2b + languageName: node + linkType: hard + "@fmvilas/pseudo-yaml-ast@npm:^0.3.1": version: 0.3.1 resolution: "@fmvilas/pseudo-yaml-ast@npm:0.3.1" @@ -9239,6 +9547,30 @@ __metadata: languageName: node linkType: hard +"@frsource/base64@npm:1.0.5": + version: 1.0.5 + resolution: "@frsource/base64@npm:1.0.5" + checksum: ba526dd81df4e91b0abbcc34fc6818c8ff132e5230c23a4448a365ba934f782a86abb2a8566050f9450905851e467a7160f01f3d321fbb0fa3c8c516c5a82b9b + languageName: node + linkType: hard + +"@frsource/cypress-plugin-visual-regression-diff@npm:^3.2.8": + version: 3.2.8 + resolution: "@frsource/cypress-plugin-visual-regression-diff@npm:3.2.8" + dependencies: + "@frsource/base64": 1.0.5 + glob: 8.0.3 + meta-png: 1.0.5 + move-file: 2.1.0 + pixelmatch: 5.3.0 + pngjs: 6.0.0 + sharp: 0.31.2 + peerDependencies: + cypress: ">=4.5.0" + checksum: 7e5a1daf3a36ec7f62ea643da8eff73aadb595e4fb8b400abec37e38a356a200de1ce47ff2e14666e71556300e4d044d5fa5ad21bdd2d214b93402addb1a490e + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1, @gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -9342,8 +9674,8 @@ __metadata: linkType: hard "@google-cloud/storage@npm:^6.0.0": - version: 6.9.1 - resolution: "@google-cloud/storage@npm:6.9.1" + version: 6.9.2 + resolution: "@google-cloud/storage@npm:6.9.2" dependencies: "@google-cloud/paginator": ^3.0.7 "@google-cloud/projectify": ^3.0.0 @@ -9362,7 +9694,7 @@ __metadata: retry-request: ^5.0.0 teeny-request: ^8.0.0 uuid: ^8.0.0 - checksum: 9967bc0e80d1531f91030d27fc46cef0242f70dde2064b051104d8d261f1d3cba38b51789b0ae0850bf99b13d093365f85c85c43a2d9468d81f0f98238f76e78 + checksum: e4962be29ca3dd722019db95f99b095993534915d663a82b41c95beaf284d878de5b1357102441e4e375de838299f6d82eff55a2c4e9f610f9a12feac21e2735 languageName: node linkType: hard @@ -9853,7 +10185,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/merge@npm:8.3.16, @graphql-tools/merge@npm:^8.2.6": +"@graphql-tools/merge@npm:8.3.16": version: 8.3.16 resolution: "@graphql-tools/merge@npm:8.3.16" dependencies: @@ -9865,6 +10197,18 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/merge@npm:8.3.18, @graphql-tools/merge@npm:^8.2.6": + version: 8.3.18 + resolution: "@graphql-tools/merge@npm:8.3.18" + dependencies: + "@graphql-tools/utils": 9.2.1 + tslib: ^2.4.0 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 0834fcf13dec5ee92e39f2e1b27a098654e2db20bf6ef6f43d7efce56b7d750caa59dd16aacb211b8f5a198d29c19d36471401762f5a34e0bc22657285dcae92 + languageName: node + linkType: hard + "@graphql-tools/mock@npm:^8.1.2": version: 8.6.8 resolution: "@graphql-tools/mock@npm:8.6.8" @@ -9974,7 +10318,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/schema@npm:9.0.14, @graphql-tools/schema@npm:^9.0.0": +"@graphql-tools/schema@npm:9.0.14": version: 9.0.14 resolution: "@graphql-tools/schema@npm:9.0.14" dependencies: @@ -9988,6 +10332,20 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/schema@npm:^9.0.0": + version: 9.0.16 + resolution: "@graphql-tools/schema@npm:9.0.16" + dependencies: + "@graphql-tools/merge": 8.3.18 + "@graphql-tools/utils": 9.2.1 + tslib: ^2.4.0 + value-or-promise: 1.0.12 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: ecbd27b4a36424c8d4b2206b1f2d2ec2cff3c66f52ec452b17977642017ca7f00df4df44f2d0426174ceea9596474d0656bc0227f4c1149f2288abb6d186cd68 + languageName: node + linkType: hard + "@graphql-tools/url-loader@npm:7.16.28, @graphql-tools/url-loader@npm:^7.13.2, @graphql-tools/url-loader@npm:^7.9.7": version: 7.16.28 resolution: "@graphql-tools/url-loader@npm:7.16.28" @@ -10066,7 +10424,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:9.1.4, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": +"@graphql-tools/utils@npm:9.1.4": version: 9.1.4 resolution: "@graphql-tools/utils@npm:9.1.4" dependencies: @@ -10077,6 +10435,18 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/utils@npm:9.2.1, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1": + version: 9.2.1 + resolution: "@graphql-tools/utils@npm:9.2.1" + dependencies: + "@graphql-typed-document-node/core": ^3.1.1 + tslib: ^2.4.0 + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 94ed12df5f49e5c338322ffd931236a687a3d5c443bf499f9baab5d4fcd9792234111142be8aa506a01ca2e82732996c4e1d8f6159ff9cc7fdc5c97f63e55226 + languageName: node + linkType: hard + "@graphql-tools/wrap@npm:9.2.23": version: 9.2.23 resolution: "@graphql-tools/wrap@npm:9.2.23" @@ -10221,6 +10591,7 @@ __metadata: resolution: "@internal/plugin-todo-list-backend@workspace:plugins/example-todo-list-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" @@ -10604,460 +10975,6 @@ __metadata: languageName: node linkType: hard -"@jimp/bmp@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/bmp@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - bmp-js: ^0.1.0 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 3a5a7600add0edf68a0d8f8397dd0ca37fa20d93b4d9ea8321875acd92e4a632a31ac1af0fc2129cff76cdc77aa77b359327613f822c0bc48781f007459e44f8 - languageName: node - linkType: hard - -"@jimp/core@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/core@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - any-base: ^1.1.0 - buffer: ^5.2.0 - core-js: ^3.4.1 - exif-parser: ^0.1.12 - file-type: ^9.0.0 - load-bmfont: ^1.3.1 - mkdirp: ^0.5.1 - phin: ^2.9.1 - pixelmatch: ^4.0.2 - tinycolor2: ^1.4.1 - checksum: f67db147a114b7a220621b80f9c65cf0d1434f4bd7ab8203b44246b79093f9ec46170a6205755eae7fe53c14d2935d8565f5a2185ccd4495ae1cd6f13bcf4852 - languageName: node - linkType: hard - -"@jimp/custom@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/custom@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/core": ^0.10.3 - core-js: ^3.4.1 - checksum: 8a282c9387cb975a533d140a8e0c9f7c23b12b6e6a92e9a1e979b7cc7d89e623189c47b0d0119aa7e497149f0d9a85e4ec14a605921527340c307b7750ba519a - languageName: node - linkType: hard - -"@jimp/gif@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/gif@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - omggif: ^1.0.9 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: a23253e6762e6f19b0fa6deaa9db3bca25b313eb5ea506dd3d844407598d86cf4188cc92c091019a4257450821ffe24f0475cc2e4a1ef24998d95d176078cf2f - languageName: node - linkType: hard - -"@jimp/jpeg@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/jpeg@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - jpeg-js: ^0.3.4 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: cb830ddf3fddbc4f833086ffbf8f21e0c73863522cce86d6f6c82d4f0183d0619ee280736c5ed07563bfcf9f884fd96bdb845a95c5a8a6e11f961f4e95cb4b24 - languageName: node - linkType: hard - -"@jimp/plugin-blit@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-blit@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 5858557359eb0405c29741c8ffe98b4bb26b42564c178402e21b74733c02e04233d2a1af095cff4cd2864ab43d79e01033559f250b3eb879600138007a7d7453 - languageName: node - linkType: hard - -"@jimp/plugin-blur@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-blur@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: d3a2e14d4dc5f3b5ad010888e70193cc8f7327aeda67989eba3f49de2e5324fa6adf89e3a7f1597343f59688ce6e299ad5818aa6c670ed8596ddfba0ca281db3 - languageName: node - linkType: hard - -"@jimp/plugin-circle@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-circle@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: d351c85f4a9aeb404302a03f5d99e6486b95f271f2c628758c8e3d1574bc268278ffc34d9d00d3221d6079431b06a5e6a5a3922863994000b5eb3c81f8c27d35 - languageName: node - linkType: hard - -"@jimp/plugin-color@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-color@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - tinycolor2: ^1.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 2014802f3b0465abbd7682336836183293a26315acbb84826f5207a374f807c574e120790738dcf51aba2cb7e9a481003289ef8bf429facb9fe36a19ce5b6924 - languageName: node - linkType: hard - -"@jimp/plugin-contain@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-contain@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - "@jimp/plugin-scale": ">=0.3.5" - checksum: 91d77621a350a733839fa8bc15880bc74ac666682a651e676797207dc4f55cba465f3695f6280f3d05122d67067a0a94f3905f323410d880484dd769055c9b49 - languageName: node - linkType: hard - -"@jimp/plugin-cover@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-cover@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-crop": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - "@jimp/plugin-scale": ">=0.3.5" - checksum: ca664509c2d42e987a56e80fa848ec3e5590a1f919c0a607d7a03b8192571456c0287a2f768785bf816ecfe7889a7a786490a408866acc94ce5306b39ca82f6b - languageName: node - linkType: hard - -"@jimp/plugin-crop@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-crop@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 54e79b6fa831f813f28dac53187dfa1684d00ece8a98433c30c1e61333ba2b5373758889d202418a55c99dffe235daf153454f35691324b42dd9a103a65d3bd2 - languageName: node - linkType: hard - -"@jimp/plugin-displace@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-displace@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 17b5792ce07ac3b7b5aa8c457626fb46ded0a8f05027c4580fac1b22428e7c2c0ff04e0ad4f7249c179322afa7921e57afc88ace03e2d08b67e864c24ef5c060 - languageName: node - linkType: hard - -"@jimp/plugin-dither@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-dither@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 77caaceebccceb73e32616fd79517d9640d217403577715e08146bf2a67599822070be8a51783ad76402e0303f6bc9afcebf75f75cc73ae44c684e3c1e1248ea - languageName: node - linkType: hard - -"@jimp/plugin-fisheye@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-fisheye@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: f60d9c6c40d6fa1b85658ffa23568f95aeab1635165f2b74266b128be0f9b4bf963cfa755e5a43b7f18421340a4bb7b628ab75821b34b602924154b55c0f39ce - languageName: node - linkType: hard - -"@jimp/plugin-flip@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-flip@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-rotate": ">=0.3.5" - checksum: 6542b9e595e3b95cf8ac741226e9089ab1edd3fa19bc4ac159afd5bc3801a55f6ee93ade029626dbde7977eb1fbca51c71d9c6546b5285754eb29b54a7f5f5ff - languageName: node - linkType: hard - -"@jimp/plugin-gaussian@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-gaussian@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 465ca178b9a9062eb6db4a57fe3b47236270bad9600cfb4aae162aad43f20e5cf90c19bf77bd08867f25abd0679c6018412e0ad8cb3777640dad5c3f51e64dd9 - languageName: node - linkType: hard - -"@jimp/plugin-invert@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-invert@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 917419301a961541466e04c7fc974fc95f35e3f95f75e6bfef141270f06b68bcdf61321cad2d545cd8115a6e3a99992345f964bdb94cbdb48aaf42885b8fcae7 - languageName: node - linkType: hard - -"@jimp/plugin-mask@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-mask@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 7870fe46d9fcec6145476bcceed23568012e87953772e7ea2b82c8ed48375ee525db6b977816574b47e08c595bd6123c8d9cd24a95e649677d0ec1fada4e6831 - languageName: node - linkType: hard - -"@jimp/plugin-normalize@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-normalize@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: f34ebf3ef03d83b2cb9a8779d39a3e10707aeae4dfe67e1bb30202589e72d09c0e9a61b429de4e4886728f0faabbb83a6ff081f2e9bf79b517e2ea387c53a9a4 - languageName: node - linkType: hard - -"@jimp/plugin-print@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-print@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - load-bmfont: ^1.4.0 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - checksum: 772a7d82741af583293006f699bbbaf116c264327412ea6ed0f3b7fb14d0dcbef51278e6fce3e966ad23e655114bfe949106d551d06459819b26e461638e8a5e - languageName: node - linkType: hard - -"@jimp/plugin-resize@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-resize@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: aff691d2936bd88d59a68b36a6f06b306d0f7c654baec7b43371e6b250397b3a19d0b98a620ad26738ed51357f5899a8002761d8f6f0ae6074e6c63905895a5d - languageName: node - linkType: hard - -"@jimp/plugin-rotate@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-rotate@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blit": ">=0.3.5" - "@jimp/plugin-crop": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: f1771365753a64387e455006467dd41e09c1e329180e57df77ef78f72dfac7d889e5d03adae1038f4c6ac081a9d5113c59541983fdda6bf08da9af852650c468 - languageName: node - linkType: hard - -"@jimp/plugin-scale@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-scale@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: 356e8ab040bf842845a29cc0a6d7170fd15c1a9e9407028b88771bff01ecb6870c8f26d15b59b432914c430e611f36f54f932aaa7a68dcc9e32efae2f6dd1946 - languageName: node - linkType: hard - -"@jimp/plugin-shadow@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-shadow@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-blur": ">=0.3.5" - "@jimp/plugin-resize": ">=0.3.5" - checksum: 7f07387160b31732b3d43a2c4d44f8716be7a08b2f0fcfd58d18ca76ed62d825629c6273434bd23d02ade6a18bc8d7c7020eb9ab0ccc95acd85e718b5ab2c7a0 - languageName: node - linkType: hard - -"@jimp/plugin-threshold@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugin-threshold@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - "@jimp/plugin-color": ">=0.8.0" - "@jimp/plugin-resize": ">=0.8.0" - checksum: 550de37f82ccfaacb954b0e183a7bfa77f80f33ec9f5b08756ce778675284e486a2b5860c69c6d15a38d1d7030f1896e1ac79e8675603ead9e36c075f3cf636e - languageName: node - linkType: hard - -"@jimp/plugins@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/plugins@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/plugin-blit": ^0.10.3 - "@jimp/plugin-blur": ^0.10.3 - "@jimp/plugin-circle": ^0.10.3 - "@jimp/plugin-color": ^0.10.3 - "@jimp/plugin-contain": ^0.10.3 - "@jimp/plugin-cover": ^0.10.3 - "@jimp/plugin-crop": ^0.10.3 - "@jimp/plugin-displace": ^0.10.3 - "@jimp/plugin-dither": ^0.10.3 - "@jimp/plugin-fisheye": ^0.10.3 - "@jimp/plugin-flip": ^0.10.3 - "@jimp/plugin-gaussian": ^0.10.3 - "@jimp/plugin-invert": ^0.10.3 - "@jimp/plugin-mask": ^0.10.3 - "@jimp/plugin-normalize": ^0.10.3 - "@jimp/plugin-print": ^0.10.3 - "@jimp/plugin-resize": ^0.10.3 - "@jimp/plugin-rotate": ^0.10.3 - "@jimp/plugin-scale": ^0.10.3 - "@jimp/plugin-shadow": ^0.10.3 - "@jimp/plugin-threshold": ^0.10.3 - core-js: ^3.4.1 - timm: ^1.6.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 28833f4ce43f911c41b5c251759f5e38406ba99249a7c00d11a81e4ce58027eb993ca0c220601c3702832c2855dbb0554762bf724107bb4fdd0a2c1cf8753895 - languageName: node - linkType: hard - -"@jimp/png@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/png@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/utils": ^0.10.3 - core-js: ^3.4.1 - pngjs: ^3.3.3 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 1520b669d0dc6a0b47d7357c5e75a080e3a56db0459fad5c56e299b03c4a7bf560540480b08fa2e1eaf283ba153efb26a3e90d90fe373069c6c6184f7ea3e163 - languageName: node - linkType: hard - -"@jimp/tiff@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/tiff@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - core-js: ^3.4.1 - utif: ^2.0.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 6ff41bc962afdbcd223b331beed232b5aecf2b0ba06cccddaef5b5d4b925fa51d6a26d226080baabd25d7dceb0b9b0e5c69b60c44494822cb69988c3221c6514 - languageName: node - linkType: hard - -"@jimp/types@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/types@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/bmp": ^0.10.3 - "@jimp/gif": ^0.10.3 - "@jimp/jpeg": ^0.10.3 - "@jimp/png": ^0.10.3 - "@jimp/tiff": ^0.10.3 - core-js: ^3.4.1 - timm: ^1.6.1 - peerDependencies: - "@jimp/custom": ">=0.3.5" - checksum: 68ea0f1a1f3116ba779c898c9fb38fb7b822addaa14ac153aea4cdc9e274efc34a46a6ad4c8a9978fb88b4ab5a826190e28b89b431dce735ee760997f2d66678 - languageName: node - linkType: hard - -"@jimp/utils@npm:^0.10.3": - version: 0.10.3 - resolution: "@jimp/utils@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - core-js: ^3.4.1 - regenerator-runtime: ^0.13.3 - checksum: bd36b8bbaaf878190afe357f1bcebed9215dae503f06603039e6a106045588003b845150cb5a5ba6dd4d973e7e7b95779158ae921011fb6bd79083c8cb177804 - languageName: node - linkType: hard - "@josephg/resolvable@npm:^1.0.0": version: 1.0.1 resolution: "@josephg/resolvable@npm:1.0.1" @@ -11152,11 +11069,11 @@ __metadata: linkType: hard "@keyv/redis@npm:^2.5.3": - version: 2.5.4 - resolution: "@keyv/redis@npm:2.5.4" + version: 2.5.5 + resolution: "@keyv/redis@npm:2.5.5" dependencies: - ioredis: ^5.2.4 - checksum: 02f557e0bc0343aea44b8dd4b6ff273da5833b935236c4036fa89e90b1d92d9688dafa064d5318d26744a6c72497cd4c41dcac825cb8d5919271e3a25a3cadbb + ioredis: ^5.3.0 + checksum: dc4c4e9c0a44dec1166a6a4481a42342289b4618136c2f640306bee381cf30d737346b064ecc369fc8ebdd2baaaba47e099aabe9f37839911171a9c006d75e62 languageName: node linkType: hard @@ -11289,7 +11206,45 @@ __metadata: languageName: node linkType: hard -"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4, @material-ui/core@npm:^4.9.10, @material-ui/core@npm:^4.9.13": +"@material-ui/core@npm:^3.9.3": + version: 3.9.4 + resolution: "@material-ui/core@npm:3.9.4" + dependencies: + "@babel/runtime": ^7.2.0 + "@material-ui/system": ^3.0.0-alpha.0 + "@material-ui/utils": ^3.0.0-alpha.2 + "@types/jss": ^9.5.6 + "@types/react-transition-group": ^2.0.8 + brcast: ^3.0.1 + classnames: ^2.2.5 + csstype: ^2.5.2 + debounce: ^1.1.0 + deepmerge: ^3.0.0 + dom-helpers: ^3.2.1 + hoist-non-react-statics: ^3.2.1 + is-plain-object: ^2.0.4 + jss: ^9.8.7 + jss-camel-case: ^6.0.0 + jss-default-unit: ^8.0.2 + jss-global: ^3.0.0 + jss-nested: ^6.0.1 + jss-props-sort: ^6.0.0 + jss-vendor-prefixer: ^7.0.0 + normalize-scroll-left: ^0.1.2 + popper.js: ^1.14.1 + prop-types: ^15.6.0 + react-event-listener: ^0.6.2 + react-transition-group: ^2.2.1 + recompose: 0.28.0 - 0.30.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: c3923bfba4ef4449fbdcd37712ec0d11393ffa396c575a05b5f9530ca1e714028882d39402eb6918dad49f2eb1c53b261cfd0f2dfed494c2dfd96ee335336b44 + languageName: node + linkType: hard + +"@material-ui/core@npm:^4.11.0, @material-ui/core@npm:^4.11.3, @material-ui/core@npm:^4.12.1, @material-ui/core@npm:^4.12.2, @material-ui/core@npm:^4.12.4": version: 4.12.4 resolution: "@material-ui/core@npm:4.12.4" dependencies: @@ -11447,6 +11402,21 @@ __metadata: languageName: node linkType: hard +"@material-ui/system@npm:^3.0.0-alpha.0": + version: 3.0.0-alpha.2 + resolution: "@material-ui/system@npm:3.0.0-alpha.2" + dependencies: + "@babel/runtime": ^7.2.0 + deepmerge: ^3.0.0 + prop-types: ^15.6.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: 3aacb8b4afe2a820844b90905cfcd86ab934108cd719f11713ee46f8a4da30cb8c50e86219e1440b3c6dd333a09d4123cd1990d9c51862c1d56ec2b36e4d7ded + languageName: node + linkType: hard + "@material-ui/system@npm:^4.12.2": version: 4.12.2 resolution: "@material-ui/system@npm:4.12.2" @@ -11490,6 +11460,20 @@ __metadata: languageName: node linkType: hard +"@material-ui/utils@npm:^3.0.0-alpha.2": + version: 3.0.0-alpha.3 + resolution: "@material-ui/utils@npm:3.0.0-alpha.3" + dependencies: + "@babel/runtime": ^7.2.0 + prop-types: ^15.6.0 + react-is: ^16.6.3 + peerDependencies: + react: ^16.3.0 + react-dom: ^16.3.0 + checksum: 589a16245338c374b604a793d9f7a05bd932c9710f78261e46176b74a61d5d308b3e36dab688988ee5177d689c53d9e9da4649eca009ea11d8aac948db27af50 + languageName: node + linkType: hard + "@material-ui/utils@npm:^4.11.2, @material-ui/utils@npm:^4.11.3, @material-ui/utils@npm:^4.7.1": version: 4.11.3 resolution: "@material-ui/utils@npm:4.11.3" @@ -11563,7 +11547,7 @@ __metadata: languageName: node linkType: hard -"@microsoft/microsoft-graph-types@npm:^2.6.0": +"@microsoft/microsoft-graph-types@npm:^2.25.0, @microsoft/microsoft-graph-types@npm:^2.6.0": version: 2.25.0 resolution: "@microsoft/microsoft-graph-types@npm:2.25.0" checksum: b311385e0a51f827082af5a016f35b1d6cd4d861121e8767b3279ab1a17475977cddbbdcc208abdddf0f953fd6ce4634d3c302e317cf50af4cb6111385347b4f @@ -12421,22 +12405,22 @@ __metadata: languageName: node linkType: hard -"@octokit/webhooks-types@npm:6.7.0": - version: 6.7.0 - resolution: "@octokit/webhooks-types@npm:6.7.0" - checksum: 407a362f88c2f46261e973ba8e2a624a971134cb3e30a3cddcb08c192f1af4f02d49f6a624819b6ee72e6abe5a214923ffb2b80ed40b0c1717f71fb91783e3d3 +"@octokit/webhooks-types@npm:6.10.0": + version: 6.10.0 + resolution: "@octokit/webhooks-types@npm:6.10.0" + checksum: 6eac226f070a48d9ef2594df952e8540b001e2a8760c4fa5ac2f78c1750694a6c3b8de42fb4dbb4bb78335f091d9268539d4261c52a1a91fb9ef1e9af1959b44 languageName: node linkType: hard "@octokit/webhooks@npm:^10.0.0": - version: 10.5.1 - resolution: "@octokit/webhooks@npm:10.5.1" + version: 10.7.0 + resolution: "@octokit/webhooks@npm:10.7.0" dependencies: "@octokit/request-error": ^3.0.0 "@octokit/webhooks-methods": ^3.0.0 - "@octokit/webhooks-types": 6.7.0 + "@octokit/webhooks-types": 6.10.0 aggregate-error: ^3.1.0 - checksum: af8e4712fb1cbbda6ec5627586f9a7a5ee0c3bb6dc3af1875c42cdf3a1b10e959f9c05a5249722d9aac2ffefe8d572b03a77975f7cd9eacea114e01ebddb959a + checksum: c86d6ae97b59b540701b14e40aca88f47352cf4c03ee0237f714b65ea49b7416d262475d340ed0b4aee851c0a2fdc7d599982d30b4e5a3431986576fbcd4e86d languageName: node linkType: hard @@ -12483,22 +12467,22 @@ __metadata: linkType: hard "@opensearch-project/opensearch@npm:^2.0.0": - version: 2.1.0 - resolution: "@opensearch-project/opensearch@npm:2.1.0" + version: 2.2.0 + resolution: "@opensearch-project/opensearch@npm:2.2.0" dependencies: aws4: ^1.11.0 debug: ^4.3.1 - hpagent: ^0.1.1 + hpagent: ^1.2.0 ms: ^2.1.3 secure-json-parse: ^2.4.0 - checksum: 900b90f35d5b960fe60979168e21e9e5b6089a8e3dd9341b5d86c7f7aa7671cbfd937fbec311a6cfe195c113db755e699d3678ee0cbf454e9a9de1189d8cc935 + checksum: cceb5bb2c194a7d4bfab3c1b4a3230ea1457ae8976f39bb9e0c5e0067dc450a418a4649536988f0d48a746d7d3ed2002c32d9fde48dfc3112158e964bafa6e76 languageName: node linkType: hard "@opentelemetry/api@npm:^1.0.1, @opentelemetry/api@npm:^1.3.0": - version: 1.3.0 - resolution: "@opentelemetry/api@npm:1.3.0" - checksum: 33d284b67b6fab20ff72961d289c6487d3cb27caf7489f0231d7030551f82871e081e744b0390751d8aef3bf1614bd79f854788901a354e15274f552581fb374 + version: 1.4.0 + resolution: "@opentelemetry/api@npm:1.4.0" + checksum: 8dc522194e20d2e8aa6cac155dbce19d3fc9cfac59e953ece1064158c6348ccd9560ee99d2f2381e82c2f8c9a129b57fa7b640027383315504de1fa712b6d7f1 languageName: node linkType: hard @@ -12708,9 +12692,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/core-v5@npm:@rjsf/core@5.0.1": - version: 5.0.1 - resolution: "@rjsf/core@npm:5.0.1" +"@rjsf/core-v5@npm:@rjsf/core@5.1.0": + version: 5.1.0 + resolution: "@rjsf/core@npm:5.1.0" dependencies: lodash: ^4.17.15 lodash-es: ^4.17.15 @@ -12719,7 +12703,7 @@ __metadata: peerDependencies: "@rjsf/utils": ^5.0.0 react: ^16.14.0 || >=17 - checksum: befd0b39aab7462f23ed926ca17314a049f338e81cdda8233e35c45febb34e3d1ff550ca8db7e64570342be281e3556a4cb045b52af86a0a551041d5ee22472b + checksum: ff38046bb25de86b57e404c5d1ccea84b0485e916caf33a3cb25b030a38ed930a9b89a411671a7c29b047da38e0c682e20b43b13e61d77df770299385ba3c67a languageName: node linkType: hard @@ -12742,16 +12726,16 @@ __metadata: languageName: node linkType: hard -"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.0.1": - version: 5.0.1 - resolution: "@rjsf/material-ui@npm:5.0.1" +"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.1.0": + version: 5.1.0 + resolution: "@rjsf/material-ui@npm:5.1.0" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.0.0 "@rjsf/utils": ^5.0.0 react: ^16.14.0 || >=17 - checksum: 041f21caef8fd8e594c3b517eea15344c97017d03de5e608b1aead3e94cca474dc874930b64f59b506c1e578889664718d07e1e580fcffc78611dad3d33099fc + checksum: f8e2c486f33a60703cae5bb42ae82bc431b3d743c239868ca71907e7b4127a39d1688200820c0c8acdf3ecd3f5eaddef4ba47264695feead28e9b439d9be7ce8 languageName: node linkType: hard @@ -12767,9 +12751,9 @@ __metadata: languageName: node linkType: hard -"@rjsf/utils@npm:5.0.1": - version: 5.0.1 - resolution: "@rjsf/utils@npm:5.0.1" +"@rjsf/utils@npm:5.1.0": + version: 5.1.0 + resolution: "@rjsf/utils@npm:5.1.0" dependencies: json-schema-merge-allof: ^0.8.1 jsonpointer: ^5.0.1 @@ -12778,21 +12762,21 @@ __metadata: react-is: ^18.2.0 peerDependencies: react: ^16.14.0 || >=17 - checksum: 7bf76106eced48cfdf3072a26306ff00d0792774dfe501b061db110e9dd2e17bead77bc9b335c85adf27926ab860c39ee4f676007f8f07e74a438f3a31004692 + checksum: 76d7caf144f98b1547067bfdc2b1baecf452c63bd9d6f2cae6c162a99154bb4d2f5033f6abc0e26ab767dca9ea743f1f5a9d796696e90dd5ed1fdca5ee3c5280 languageName: node linkType: hard -"@rjsf/validator-ajv8@npm:5.0.1": - version: 5.0.1 - resolution: "@rjsf/validator-ajv8@npm:5.0.1" +"@rjsf/validator-ajv8@npm:5.1.0": + version: 5.1.0 + resolution: "@rjsf/validator-ajv8@npm:5.1.0" dependencies: - ajv: ^8.11.0 + ajv: ^8.12.0 ajv-formats: ^2.1.1 lodash: ^4.17.15 lodash-es: ^4.17.15 peerDependencies: "@rjsf/utils": ^5.0.0 - checksum: 7d36dac876fd3536dda26af5726e847af02a9880fac9feb2683809e8c1f3743e4f5ff8399e961a79f5383e28fdb5a1e9695d89ebf7dffaa22dd76948be830c54 + checksum: 3430a0aea8235deedd306b535ea3a62a9bcdd4dcf0bf1d022fe036041dceb5ca7c147b17ae50a0d25bb7c953729e987d96c68f5220f8fde4b56a89cf3f106a49 languageName: node linkType: hard @@ -13083,9 +13067,9 @@ __metadata: linkType: hard "@sideway/formula@npm:^3.0.0": - version: 3.0.0 - resolution: "@sideway/formula@npm:3.0.0" - checksum: 8ae26a0ed6bc84f7310be6aae6eb9d81e97f382619fc69025d346871a707eaab0fa38b8c857e3f0c35a19923de129f42d35c50b8010c928d64aab41578580ec4 + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a languageName: node linkType: hard @@ -13399,90 +13383,90 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-arm64@npm:1.3.30" +"@swc/core-darwin-arm64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-arm64@npm:1.3.34" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-darwin-x64@npm:1.3.30" +"@swc/core-darwin-x64@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-darwin-x64@npm:1.3.34" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.30" +"@swc/core-linux-arm-gnueabihf@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.34" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@swc/core-linux-arm64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.30" +"@swc/core-linux-arm64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.30" +"@swc/core-linux-arm64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.34" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.30" +"@swc/core-linux-x64-gnu@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-linux-x64-musl@npm:1.3.30" +"@swc/core-linux-x64-musl@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-linux-x64-musl@npm:1.3.34" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.30" +"@swc/core-win32-arm64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.34" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.30" +"@swc/core-win32-ia32-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.34" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.30": - version: 1.3.30 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.30" +"@swc/core-win32-x64-msvc@npm:1.3.34": + version: 1.3.34 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.34" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.9": - version: 1.3.30 - resolution: "@swc/core@npm:1.3.30" + version: 1.3.34 + resolution: "@swc/core@npm:1.3.34" dependencies: - "@swc/core-darwin-arm64": 1.3.30 - "@swc/core-darwin-x64": 1.3.30 - "@swc/core-linux-arm-gnueabihf": 1.3.30 - "@swc/core-linux-arm64-gnu": 1.3.30 - "@swc/core-linux-arm64-musl": 1.3.30 - "@swc/core-linux-x64-gnu": 1.3.30 - "@swc/core-linux-x64-musl": 1.3.30 - "@swc/core-win32-arm64-msvc": 1.3.30 - "@swc/core-win32-ia32-msvc": 1.3.30 - "@swc/core-win32-x64-msvc": 1.3.30 + "@swc/core-darwin-arm64": 1.3.34 + "@swc/core-darwin-x64": 1.3.34 + "@swc/core-linux-arm-gnueabihf": 1.3.34 + "@swc/core-linux-arm64-gnu": 1.3.34 + "@swc/core-linux-arm64-musl": 1.3.34 + "@swc/core-linux-x64-gnu": 1.3.34 + "@swc/core-linux-x64-musl": 1.3.34 + "@swc/core-win32-arm64-msvc": 1.3.34 + "@swc/core-win32-ia32-msvc": 1.3.34 + "@swc/core-win32-x64-msvc": 1.3.34 dependenciesMeta: "@swc/core-darwin-arm64": optional: true @@ -13504,7 +13488,7 @@ __metadata: optional: true "@swc/core-win32-x64-msvc": optional: true - checksum: 157a8ae43ebc73fa28d53e913fd7fc879289d5479ba5ea0c5e9abad0b379ca7e292d45f4f07bfd3ec0ff1998b55f300737724dfe463f1f7b361661e083db950c + checksum: a77c286b6b34d40f634ae882aac66f882cf806c165453878c31311070c46f020c607925bd454f64959504f08852b204cc37feba93fc6a3c1a64b295a9b5007d6 languageName: node linkType: hard @@ -13538,18 +13522,18 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.22.0": - version: 4.22.0 - resolution: "@tanstack/query-core@npm:4.22.0" - checksum: d24c13f8e21b65380230055a6673ae670aca5ee550c2f9a24b89fd3ac5243b465bb25f61b29da8ca285fc7fb0f4c2f8add3864f742eafac5131e777f3e52767a +"@tanstack/query-core@npm:4.24.4": + version: 4.24.4 + resolution: "@tanstack/query-core@npm:4.24.4" + checksum: b357e950a41e5769878a3bfe9dd56a66828ccebb2f9396e568e8835bed71eb37926770a461e3aa5bafb7e1121c5141cee86aedf3ced88a2eacf754d545b107cd languageName: node linkType: hard "@tanstack/react-query@npm:^4.1.3": - version: 4.22.0 - resolution: "@tanstack/react-query@npm:4.22.0" + version: 4.24.4 + resolution: "@tanstack/react-query@npm:4.24.4" dependencies: - "@tanstack/query-core": 4.22.0 + "@tanstack/query-core": 4.24.4 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -13560,7 +13544,7 @@ __metadata: optional: true react-native: optional: true - checksum: b146774b44a79dd5a6412d981ce04790e66da5a36f907a03c85c36f50a38fb4e4dfbfca7b1561c86b39fb0df1c0c1ae0a0ef2930c06b444da3f430b9bad450f1 + checksum: 8cf008d690fc5d336f6471ea2bc0751189f03874dcc7930cf8944fb57fa34e3b5347823775dbd36629d53a7aacb9ce87482b1adb3ad80d277a3a6c73b797f6a2 languageName: node linkType: hard @@ -13574,6 +13558,7 @@ __metadata: "@backstage/cli-common": "workspace:^" "@backstage/config": "workspace:^" "@backstage/plugin-techdocs-node": "workspace:^" + "@frsource/cypress-plugin-visual-regression-diff": ^3.2.8 "@types/commander": ^2.12.2 "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 @@ -13583,7 +13568,6 @@ __metadata: "@types/webpack-env": ^1.15.3 commander: ^9.1.0 cypress: ^10.0.0 - cypress-plugin-snapshots: ^1.4.4 dockerode: ^3.3.1 find-process: ^1.4.5 fs-extra: ^10.0.1 @@ -14073,6 +14057,15 @@ __metadata: languageName: node linkType: hard +"@types/cross-spawn@npm:^6.0.2": + version: 6.0.2 + resolution: "@types/cross-spawn@npm:6.0.2" + dependencies: + "@types/node": "*" + checksum: fa9edd32178878cab3ea8d6d0260639e0fe4860ddb3887b8de53d6e8036e154fc5f313c653f690975aa25025aea8beb83fb0870b931bf8d9202c3ac530a24c9d + languageName: node + linkType: hard + "@types/d3-color@npm:*": version: 3.0.2 resolution: "@types/d3-color@npm:3.0.2" @@ -14638,7 +14631,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.11 resolution: "@types/json-schema@npm:7.0.11" checksum: 527bddfe62db9012fccd7627794bd4c71beb77601861055d87e3ee464f2217c85fca7a4b56ae677478367bbd248dbde13553312b7d4dbc702a2f2bbf60c4018d @@ -14677,6 +14670,16 @@ __metadata: languageName: node linkType: hard +"@types/jss@npm:^9.5.6": + version: 9.5.8 + resolution: "@types/jss@npm:9.5.8" + dependencies: + csstype: ^2.0.0 + indefinite-observable: ^1.0.1 + checksum: 6e51707529a15f2f5ff94555ecb555d29427fd10c4f3d2d29474934292e365c2dfaa4ad30b2ab46946201cbca7f6e8df56513a22fc6ceca10a979db8338935c5 + languageName: node + linkType: hard + "@types/jwt-decode@npm:^3.1.0": version: 3.1.0 resolution: "@types/jwt-decode@npm:3.1.0" @@ -14869,9 +14872,9 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>= 8, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^18.11.17": - version: 18.11.18 - resolution: "@types/node@npm:18.11.18" - checksum: 03f17f9480f8d775c8a72da5ea7e9383db5f6d85aa5fefde90dd953a1449bd5e4ffde376f139da4f3744b4c83942166d2a7603969a6f8ea826edfb16e6e3b49d + version: 18.11.19 + resolution: "@types/node@npm:18.11.19" + checksum: d7cd19fcfc59cbdd3f9ba0b4072cb7adc21bd575bd8eb7d7e698975e63564aaa83f03434f32b12331f84f73d0b369d9cbe2371e359d9d7f5c3361f4987f4f7da languageName: node linkType: hard @@ -14911,9 +14914,9 @@ __metadata: linkType: hard "@types/node@npm:^16.0.0, @types/node@npm:^16.11.26, @types/node@npm:^16.9.2": - version: 16.18.11 - resolution: "@types/node@npm:16.18.11" - checksum: 2a3b1da13063debe6e26f732defb5f03ef4ef732c3e08daba838d8850433bd00e537ce1a97ce9bcfc4b15db5218d701d1265fae94e0d6926906bec157e6b46e0 + version: 16.18.12 + resolution: "@types/node@npm:16.18.12" + checksum: fc3271182414f8593018ef8f00b4718116a92f463f619081bd399d9460e7861e1dd7eebc7cf94c23567e418ff397babed077011711aae8d47171b5a81c5bd71d languageName: node linkType: hard @@ -15136,6 +15139,15 @@ __metadata: languageName: node linkType: hard +"@types/react-transition-group@npm:^2.0.8": + version: 2.9.2 + resolution: "@types/react-transition-group@npm:2.9.2" + dependencies: + "@types/react": "*" + checksum: 6f30fffc221339de90bd3e999f32328618cfaedfcaa501603f5ddc5bed1c2dbaa0d51347c3a25e5f8fd3041c671aabd2b7bfbcad611a7636adcd9da4e0666fa5 + languageName: node + linkType: hard + "@types/react-transition-group@npm:^4.2.0": version: 4.2.4 resolution: "@types/react-transition-group@npm:4.2.4" @@ -16297,13 +16309,6 @@ __metadata: languageName: node linkType: hard -"after@npm:0.8.2": - version: 0.8.2 - resolution: "after@npm:0.8.2" - checksum: 52ea9be2e97d764de256dfb3843d68cb180d2d464748010ea0d8079ee28190190080a53e4005a62adbf4337c2d613906db82f08c0091cccb8e817625ccf94c52 - languageName: node - linkType: hard - "agent-base@npm:6, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -16380,7 +16385,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0, ajv@npm:^8.8.0": +"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.12.0, ajv@npm:^8.8.0": version: 8.12.0 resolution: "ajv@npm:8.12.0" dependencies: @@ -16500,13 +16505,6 @@ __metadata: languageName: node linkType: hard -"any-base@npm:^1.1.0": - version: 1.1.0 - resolution: "any-base@npm:1.1.0" - checksum: c1fd040de52e710e2de7d9ae4df52bac589f35622adb24686c98ce21c7b824859a8db9614bc119ed8614f42fd08918b2612e6a6c385480462b3100a1af59289d - languageName: node - linkType: hard - "any-promise@npm:^1.0.0": version: 1.3.0 resolution: "any-promise@npm:1.3.0" @@ -16811,7 +16809,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.4, array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": +"array-includes@npm:^3.1.5, array-includes@npm:^3.1.6": version: 3.1.6 resolution: "array-includes@npm:3.1.6" dependencies: @@ -16824,15 +16822,6 @@ __metadata: languageName: node linkType: hard -"array-union@npm:^1.0.1": - version: 1.0.2 - resolution: "array-union@npm:1.0.2" - dependencies: - array-uniq: ^1.0.1 - checksum: 82cec6421b6e6766556c484835a6d476a873f1b71cace5ab2b4f1b15b1e3162dc4da0d16f7a2b04d4aec18146c6638fe8f661340b31ba8e469fd811a1b45dc8d - languageName: node - linkType: hard - "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -16840,22 +16829,15 @@ __metadata: languageName: node linkType: hard -"array-uniq@npm:^1.0.1": - version: 1.0.3 - resolution: "array-uniq@npm:1.0.3" - checksum: 1625f06b093d8bf279b81adfec6e72951c0857d65b5e3f65f053fffe9f9dd61c2fc52cff57e38a4700817e7e3f01a4faa433d505ea9e33cdae4514c334e0bf9e - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.2.5": - version: 1.3.0 - resolution: "array.prototype.flat@npm:1.3.0" +"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.3.1": + version: 1.3.1 + resolution: "array.prototype.flat@npm:1.3.1" dependencies: call-bind: ^1.0.2 - define-properties: ^1.1.3 - es-abstract: ^1.19.2 + define-properties: ^1.1.4 + es-abstract: ^1.20.4 es-shim-unscopables: ^1.0.0 - checksum: 2a652b3e8dc0bebb6117e42a5ab5738af0203a14c27341d7bb2431467bdb4b348e2c5dc555dfcda8af0a5e4075c400b85311ded73861c87290a71a17c3e0a257 + checksum: 5a8415949df79bf6e01afd7e8839bbde5a3581300e8ad5d8449dea52639e9e59b26a467665622783697917b43bf39940a6e621877c7dd9b3d1c1f97484b9b88b languageName: node linkType: hard @@ -16884,13 +16866,6 @@ __metadata: languageName: node linkType: hard -"arraybuffer.slice@npm:~0.0.7": - version: 0.0.7 - resolution: "arraybuffer.slice@npm:0.0.7" - checksum: c6bacada71e8fe3e63c5f5ac5f23810e617faa1bcf33be21db43f40819edc7e186172d4a6fb8f1b9baea26689fc8da6ddeb78cefa2cc9723156c0247c3587118 - languageName: node - linkType: hard - "arrify@npm:^1.0.1": version: 1.0.1 resolution: "arrify@npm:1.0.1" @@ -17059,6 +17034,13 @@ __metadata: languageName: node linkType: hard +"avsc@npm:^5.7.3": + version: 5.7.7 + resolution: "avsc@npm:5.7.7" + checksum: e3361aa88a61397b3345876263f79c8c8bfe013d849142202758205459a37e24cdbf02edc49ae019d6e82d93bbc7bc73e9e7fefca049aae91626bae28de4d1a9 + languageName: node + linkType: hard + "aws-lambda@npm:^1.0.7": version: 1.0.7 resolution: "aws-lambda@npm:1.0.7" @@ -17436,7 +17418,7 @@ __metadata: languageName: node linkType: hard -"backo2@npm:1.0.2, backo2@npm:^1.0.2": +"backo2@npm:^1.0.2": version: 1.0.2 resolution: "backo2@npm:1.0.2" checksum: fda8d0a0f4810068d23715f2f45153146d6ee8f62dd827ce1e0b6cc3c8328e84ad61e11399a83931705cef702fe7cbb457856bf99b9bd10c4ed57b0786252385 @@ -17478,13 +17460,6 @@ __metadata: languageName: node linkType: hard -"base64-arraybuffer@npm:0.1.4": - version: 0.1.4 - resolution: "base64-arraybuffer@npm:0.1.4" - checksum: d249a929e27b2430d7ba1527e91a36e14da37ae2f80e350c4d696a038257718f8da07577e820e7262f86a0ecd573c283db10c46502080f53ae11bfdd99b6a029 - languageName: node - linkType: hard - "base64-js@npm:^1.0.2, base64-js@npm:^1.3.0, base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" @@ -17499,13 +17474,6 @@ __metadata: languageName: node linkType: hard -"base64id@npm:2.0.0": - version: 2.0.0 - resolution: "base64id@npm:2.0.0" - checksum: 581b1d37e6cf3738b7ccdd4d14fe2bfc5c238e696e2720ee6c44c183b838655842e22034e53ffd783f872a539915c51b0d4728a49c7cc678ac5a758e00d62168 - languageName: node - linkType: hard - "base64url@npm:3.x.x": version: 3.0.1 resolution: "base64url@npm:3.0.1" @@ -17555,13 +17523,13 @@ __metadata: linkType: hard "better-sqlite3@npm:^8.0.0": - version: 8.0.1 - resolution: "better-sqlite3@npm:8.0.1" + version: 8.1.0 + resolution: "better-sqlite3@npm:8.1.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.0 - checksum: 533b2cc32bd54e2a943a4f63e079f8cc8945879b7a0ebd2085b948824ea067792f6f903ab75ba75d7cafc5f8f973354cdf9a042fa6216e077925d07a8df1bead + checksum: 7e6b4c33142f4b2ee2e60d3926b4db682feb0d09554efdaf7bea53cd5bef406ca0a5115ab9b411458daa45ba14973252ebd6853a3cdf94e4fd49cc8291730ade languageName: node linkType: hard @@ -17667,13 +17635,6 @@ __metadata: languageName: node linkType: hard -"blob@npm:0.0.5": - version: 0.0.5 - resolution: "blob@npm:0.0.5" - checksum: ca6a025f1108b7fd317fba0a0d64424f5cf47be6f4653ec8ba44777804a4e5c86c8d7a7e41f75fe52fd77c5bfc3479f68e017abe649a241c15c3fc07bfc59e7b - languageName: node - linkType: hard - "bluebird@npm:3.7.2, bluebird@npm:^3.3.5, bluebird@npm:^3.5.5, bluebird@npm:^3.7.2": version: 3.7.2 resolution: "bluebird@npm:3.7.2" @@ -17681,13 +17642,6 @@ __metadata: languageName: node linkType: hard -"bmp-js@npm:^0.1.0": - version: 0.1.0 - resolution: "bmp-js@npm:0.1.0" - checksum: 2f6cf7eeabae2aa50eb768122f59e9752caa97248028cb8b5cf0d9db7cf8fb3a60262aeb2c6889dd21357ab061b2fb318f21f20d2b24963ba36ead8e264c6654 - languageName: node - linkType: hard - "bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.1.1, bn.js@npm:^4.11.9": version: 4.12.0 resolution: "bn.js@npm:4.12.0" @@ -17783,6 +17737,13 @@ __metadata: languageName: node linkType: hard +"brcast@npm:^3.0.1": + version: 3.0.2 + resolution: "brcast@npm:3.0.2" + checksum: 7abae42088c6ffad9ff9e0fc756607a1764e299d737b3007fa49a73a38b3fda1e51362713f645db7991878ca388de94942011188450324c3debd08509315fa94 + languageName: node + linkType: hard + "breakword@npm:^1.0.5": version: 1.0.5 resolution: "breakword@npm:1.0.5" @@ -17928,13 +17889,6 @@ __metadata: languageName: node linkType: hard -"buffer-equal@npm:0.0.1": - version: 0.0.1 - resolution: "buffer-equal@npm:0.0.1" - checksum: ca4b52e6c01143529d957a78cb9a93e4257f172bbab30d9eb87c20ae085ed23c5e07f236ac051202dacbf3d17aba42e1455f84cba21ea79b67d57f2b05e9a613 - languageName: node - linkType: hard - "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -17977,7 +17931,7 @@ __metadata: languageName: node linkType: hard -"buffer@npm:^5.2.0, buffer@npm:^5.2.1, buffer@npm:^5.5.0, buffer@npm:^5.6.0": +"buffer@npm:^5.2.1, buffer@npm:^5.5.0, buffer@npm:^5.6.0": version: 5.7.1 resolution: "buffer@npm:5.7.1" dependencies: @@ -18365,6 +18319,13 @@ __metadata: languageName: node linkType: hard +"change-emitter@npm:^0.1.2": + version: 0.1.6 + resolution: "change-emitter@npm:0.1.6" + checksum: 0ed494ba9901ca56ea6f942668fd294465c334a9a0981dca96da5aea5e387c0023a630d7c658c1b532d203db54c928ddca2564e434b4a8b7f6d39155d09db255 + languageName: node + linkType: hard + "char-regex@npm:^1.0.2": version: 1.0.2 resolution: "char-regex@npm:1.0.2" @@ -18621,6 +18582,17 @@ __metadata: languageName: node linkType: hard +"clipboard@npm:^2.0.4": + version: 2.0.11 + resolution: "clipboard@npm:2.0.11" + dependencies: + good-listener: ^1.2.2 + select: ^1.1.2 + tiny-emitter: ^2.0.0 + checksum: 413055a6038e43898e0e895216b58ed54fbf386f091cb00188875ef35b186cefbd258acdf4cb4b0ac87cbc00de936f41b45dde9fe1fd1a57f7babb28363b8748 + languageName: node + linkType: hard + "cliui@npm:^3.2.0": version: 3.2.0 resolution: "cliui@npm:3.2.0" @@ -18886,7 +18858,7 @@ __metadata: languageName: node linkType: hard -"color@npm:^4.0.1": +"color@npm:^4.0.1, color@npm:^4.2.3": version: 4.2.3 resolution: "color@npm:4.2.3" dependencies: @@ -19055,6 +19027,20 @@ __metadata: languageName: node linkType: hard +"commonmark@npm:^0.29.0": + version: 0.29.3 + resolution: "commonmark@npm:0.29.3" + dependencies: + entities: ~2.0 + mdurl: ~1.0.1 + minimist: ">=1.2.2" + string.prototype.repeat: ^0.2.0 + bin: + commonmark: bin/commonmark + checksum: 892b603aeffea6a04770ce24979fc4024d2d92ca6d5146353398faab15be980af6802f3d7b35357400b870e752a9f80b766fed5c09ca063a2951c8c26013876c + languageName: node + linkType: hard + "compare-versions@npm:4.1.3": version: 4.1.3 resolution: "compare-versions@npm:4.1.3" @@ -19062,34 +19048,13 @@ __metadata: languageName: node linkType: hard -"component-bind@npm:1.0.0": - version: 1.0.0 - resolution: "component-bind@npm:1.0.0" - checksum: 746c5810b9f8735643840ad04072e1ab817444d44dc1aadc813f1f1a17c47c27616584caa0db93db7e687bfe73b65073d8246c785bcdac80f8f3627d3bb26883 - languageName: node - linkType: hard - -"component-emitter@npm:1.2.1": - version: 1.2.1 - resolution: "component-emitter@npm:1.2.1" - checksum: 00599b827635cab65bb20e5e3e2db4cea120b76b6626ce3ac6c85d7f5f39bbadd9fec530da444380035dd1c8ff08f9badca54d40b68feaf74bc64f75d537ef61 - languageName: node - linkType: hard - -"component-emitter@npm:^1.3.0, component-emitter@npm:~1.3.0": +"component-emitter@npm:^1.3.0": version: 1.3.0 resolution: "component-emitter@npm:1.3.0" checksum: b3c46de38ffd35c57d1c02488355be9f218e582aec72d72d1b8bbec95a3ac1b38c96cd6e03ff015577e68f550fbb361a3bfdbd9bb248be9390b7b3745691be6b languageName: node linkType: hard -"component-inherit@npm:0.0.3": - version: 0.0.3 - resolution: "component-inherit@npm:0.0.3" - checksum: 9f5b872a6b3a396cf827d471d07db5626d7918202ab6c1d59f2b849bab18ce4fe61d9b2b7b6ae5cd547b81f27a3de5ae678f438bfe4fadce8f26a1526ba86a74 - languageName: node - linkType: hard - "compress-commons@npm:^4.1.0": version: 4.1.0 resolution: "compress-commons@npm:4.1.0" @@ -19333,7 +19298,7 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.4.2, cookie@npm:^0.4.2, cookie@npm:~0.4.1": +"cookie@npm:0.4.2, cookie@npm:^0.4.2": version: 0.4.2 resolution: "cookie@npm:0.4.2" checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b @@ -19380,6 +19345,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^1.0.0": + version: 1.2.7 + resolution: "core-js@npm:1.2.7" + checksum: 0b76371bfa98708351cde580f9287e2360d2209920e738ae950ae74ad08639a2e063541020bf666c28778956fc356ed9fe56d962129c88a87a6a4a0612526c75 + languageName: node + linkType: hard + "core-js@npm:^2.4.0, core-js@npm:^2.5.0": version: 2.6.12 resolution: "core-js@npm:2.6.12" @@ -19387,7 +19359,7 @@ __metadata: languageName: node linkType: hard -"core-js@npm:^3.4.1, core-js@npm:^3.6.5": +"core-js@npm:^3.6.5": version: 3.27.2 resolution: "core-js@npm:3.27.2" checksum: 718debd426f55a6b97cf9b757c936be258afd6d4f7052f89d0f96c982d7013e9000b0b006df42831a0cf32adad298e34d6a19052dce9ae1c7ab87162c0c665e0 @@ -19554,11 +19526,11 @@ __metadata: linkType: hard "cronstrue@npm:^2.2.0": - version: 2.21.0 - resolution: "cronstrue@npm:2.21.0" + version: 2.22.0 + resolution: "cronstrue@npm:2.22.0" bin: cronstrue: bin/cli.js - checksum: c77206339b22c30f0d0c584dad19614cd29d712a00afc3cd5d6ebab8b5e651883e72c04832b82b55c4dcf4f6a9daff6c6c7023364770f7dff82ada29616d40a5 + checksum: 5017cccddee819c162d3b71c2a517c2468834f6454e9ce6a21016149848a69cf7f7433584c61dd1b92adea79ea461da291d32f48129c0a5ccef93019be93494f languageName: node linkType: hard @@ -19744,6 +19716,15 @@ __metadata: languageName: node linkType: hard +"css-vendor@npm:^0.3.8": + version: 0.3.8 + resolution: "css-vendor@npm:0.3.8" + dependencies: + is-in-browser: ^1.0.2 + checksum: 0a2e0cd0d4adbfdb6236950e7f9697b8a9b294eb2ae7c95996a95d273d2a63316ce793cb4654ae048aa3c129327124d2a29aada9935a0c284f9cc341c2768c8a + languageName: node + linkType: hard + "css-vendor@npm:^2.0.8": version: 2.0.8 resolution: "css-vendor@npm:2.0.8" @@ -19885,10 +19866,10 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^2.5.2, csstype@npm:^2.6.7": - version: 2.6.17 - resolution: "csstype@npm:2.6.17" - checksum: 6eee5cf81a4b1b2f0e8707b4accd7504f7cceb4b5a496d58c6e4fcea1a70c1443a975e45d722c892d372ffe788fa278ddfe4d70c5f881375f34e48bb99c70ecc +"csstype@npm:^2.0.0, csstype@npm:^2.5.2, csstype@npm:^2.6.7": + version: 2.6.21 + resolution: "csstype@npm:2.6.21" + checksum: 2ce8bc832375146eccdf6115a1f8565a27015b74cce197c35103b4494955e9516b246140425ad24103864076aa3e1257ac9bab25a06c8d931dd87a6428c9dccf languageName: node linkType: hard @@ -19932,31 +19913,6 @@ __metadata: languageName: node linkType: hard -"cypress-plugin-snapshots@npm:^1.4.4": - version: 1.4.4 - resolution: "cypress-plugin-snapshots@npm:1.4.4" - dependencies: - diff2html: ^2.7.0 - fs-extra: ^7.0.1 - image-size: ^0.7.2 - jimp: ^0.10.3 - js-base64: ^2.5.1 - lodash: ^4.17.13 - pixelmatch: ^4.0.2 - pngjs: ^3.3.3 - prettier: ^1.16.4 - rimraf: ^2.6.3 - sanitize-filename: ^1.6.1 - socket.io: ^2.2.0 - socket.io-client: ^2.2.0 - source-map-support: ^0.5.10 - unidiff: 1.0.2 - peerDependencies: - cypress: ^4.5.0 - checksum: 75b8d6b6e0353f7d2ac617c503f33c84c7c5f4e650dbaf59a76558e971bcc82532d2ac37b9eeccb7382354a13fe5d0068c8e97a9f7f6f1af6135cf5286c285f9 - languageName: node - linkType: hard - "cypress@npm:^10.0.0": version: 10.11.0 resolution: "cypress@npm:10.11.0" @@ -20287,14 +20243,14 @@ __metadata: languageName: node linkType: hard -"debounce@npm:^1.2.0": - version: 1.2.0 - resolution: "debounce@npm:1.2.0" - checksum: e39cb593ae26344921f5a2681b40b703bdd22bc43b179f0e7515176c790997932b3a0ee6ea9864f384c6ac58cecc08158fb102c3632d5d88ab621f8230ee39ff +"debounce@npm:^1.1.0, debounce@npm:^1.2.0": + version: 1.2.1 + resolution: "debounce@npm:1.2.1" + checksum: 682a89506d9e54fb109526f4da255c5546102fbb8e3ae75eef3b04effaf5d4853756aee97475cd4650641869794e44f410eeb20ace2b18ea592287ab2038519e languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.6.0, debug@npm:^2.6.9": +"debug@npm:2.6.9, debug@npm:^2.6.0": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -20324,24 +20280,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:~3.1.0": - version: 3.1.0 - resolution: "debug@npm:3.1.0" - dependencies: - ms: 2.0.0 - checksum: 0b52718ab957254a5b3ca07fc34543bc778f358620c206a08452251eb7fc193c3ea3505072acbf4350219c14e2d71ceb7bdaa0d3370aa630b50da790458d08b3 - languageName: node - linkType: hard - -"debug@npm:~4.1.0": - version: 4.1.1 - resolution: "debug@npm:4.1.1" - dependencies: - ms: ^2.1.1 - checksum: 1e681f5cce94ba10f8dde74b20b42e4d8cf0d2a6700f4c165bb3bb6885565ef5ca5885bf07e704974a835f2415ff095a63164f539988a1f07e8a69fe8b1d65ad - languageName: node - linkType: hard - "debuglog@npm:^1.0.1": version: 1.0.1 resolution: "debuglog@npm:1.0.1" @@ -20460,6 +20398,13 @@ __metadata: languageName: node linkType: hard +"deepmerge@npm:^3.0.0": + version: 3.3.0 + resolution: "deepmerge@npm:3.3.0" + checksum: 4322195389e0170a0443c07b36add19b90249802c4b47b96265fdc5f5d8beddf491d5e50cbc5bfd65f85ccf76598173083863c202f5463b3b667aca8be75d5ac + languageName: node + linkType: hard + "deepmerge@npm:^4.2.2, deepmerge@npm:~4.2.2": version: 4.2.2 resolution: "deepmerge@npm:4.2.2" @@ -20539,6 +20484,13 @@ __metadata: languageName: node linkType: hard +"delegate@npm:^3.1.2": + version: 3.2.0 + resolution: "delegate@npm:3.2.0" + checksum: d943058fe05897228b158cbd1bab05164df28c8f54127873231d6b03b0a5acc1b3ee1f98ac70ccc9b79cd84aa47118a7de111fee2923753491583905069da27d + languageName: node + linkType: hard + "delegates@npm:^1.0.0": version: 1.0.0 resolution: "delegates@npm:1.0.0" @@ -20546,10 +20498,10 @@ __metadata: languageName: node linkType: hard -"denque@npm:^2.0.1": - version: 2.0.1 - resolution: "denque@npm:2.0.1" - checksum: ec398d1e3c6c8d4f5213dcf9ad74d7faa3b461e29a0019c9742b49a97ac5e16aa7134db45fa9d841e318e7722dd1ba670a474fde9a5b0d870b3a5fc6fe914c30 +"denque@npm:^2.0.1, denque@npm:^2.1.0": + version: 2.1.0 + resolution: "denque@npm:2.1.0" + checksum: 1d4ae1d05e59ac3a3481e7b478293f4b4c813819342273f3d5b826c7ffa9753c520919ba264f377e09108d24ec6cf0ec0ac729a5686cbb8f32d797126c5dae74 languageName: node linkType: hard @@ -20621,7 +20573,7 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.0": +"detect-libc@npm:^2.0.0, detect-libc@npm:^2.0.1": version: 2.0.1 resolution: "detect-libc@npm:2.0.1" checksum: ccb05fcabbb555beb544d48080179c18523a343face9ee4e1a86605a8715b4169f94d663c21a03c310ac824592f2ba9a5270218819bb411ad7be578a527593d7 @@ -20686,18 +20638,6 @@ __metadata: languageName: node linkType: hard -"diff2html@npm:^2.7.0": - version: 2.12.2 - resolution: "diff2html@npm:2.12.2" - dependencies: - diff: ^4.0.1 - hogan.js: ^3.0.2 - merge: ^1.2.1 - whatwg-fetch: ^3.0.0 - checksum: 4d659fb558575406881bc9e6b892a236d038bca1335cbdde65ebfde462cf1cff7a7ab4a2e82d9874205e658dd2caa31699ba24ea4efb714d7c7277ddb96c7768 - languageName: node - linkType: hard - "diff3@npm:0.0.3": version: 0.0.3 resolution: "diff3@npm:0.0.3" @@ -20705,13 +20645,6 @@ __metadata: languageName: node linkType: hard -"diff@npm:^2.2.2": - version: 2.2.3 - resolution: "diff@npm:2.2.3" - checksum: b5b6fbe1848c621ef6f6c154e689842f7bb992b4c0ae257b70f5577b0906812537bf2eccda14d0215f90579567c8880eb44f1cf3851bd615583214a4f4d61ce3 - languageName: node - linkType: hard - "diff@npm:^4.0.1": version: 4.0.2 resolution: "diff@npm:4.0.2" @@ -20737,15 +20670,6 @@ __metadata: languageName: node linkType: hard -"dir-glob@npm:^2.0.0": - version: 2.2.2 - resolution: "dir-glob@npm:2.2.2" - dependencies: - path-type: ^3.0.0 - checksum: 3aa48714a9f7845ffc30ab03a5c674fe760477cc55e67b0847333371549227d93953e6627ec160f75140c5bea5c5f88d13c01de79bd1997a588efbcf06980842 - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -20837,7 +20761,7 @@ __metadata: languageName: node linkType: hard -"dom-helpers@npm:^3.4.0": +"dom-helpers@npm:^3.2.1, dom-helpers@npm:^3.4.0": version: 3.4.0 resolution: "dom-helpers@npm:3.4.0" dependencies: @@ -20878,13 +20802,6 @@ __metadata: languageName: node linkType: hard -"dom-walk@npm:^0.1.0": - version: 0.1.1 - resolution: "dom-walk@npm:0.1.1" - checksum: f55db10d0344b87cca1046a2356915a8e9ddee90fc97d3ebb26c4021e593cce47d24cbef18aac721421787c6a60fa14dd079a0b81f8610c9aeeec52177fd2acf - languageName: node - linkType: hard - "domain-browser@npm:^1.1.1": version: 1.2.0 resolution: "domain-browser@npm:1.2.0" @@ -21191,7 +21108,7 @@ __metadata: languageName: node linkType: hard -"encoding@npm:^0.1.12, encoding@npm:^0.1.13": +"encoding@npm:^0.1.11, encoding@npm:^0.1.12, encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" dependencies: @@ -21209,52 +21126,6 @@ __metadata: languageName: node linkType: hard -"engine.io-client@npm:~3.5.0": - version: 3.5.2 - resolution: "engine.io-client@npm:3.5.2" - dependencies: - component-emitter: ~1.3.0 - component-inherit: 0.0.3 - debug: ~3.1.0 - engine.io-parser: ~2.2.0 - has-cors: 1.1.0 - indexof: 0.0.1 - parseqs: 0.0.6 - parseuri: 0.0.6 - ws: ~7.4.2 - xmlhttprequest-ssl: ~1.6.2 - yeast: 0.1.2 - checksum: 2a4a8407ea939c45826d3483e39fe017e66d488dfd101282a79644f75196f7b84cac9d6f981e3ace1ab231e2469c18b25d79b114f20ab58d0eaa393bf66f213e - languageName: node - linkType: hard - -"engine.io-parser@npm:~2.2.0": - version: 2.2.1 - resolution: "engine.io-parser@npm:2.2.1" - dependencies: - after: 0.8.2 - arraybuffer.slice: ~0.0.7 - base64-arraybuffer: 0.1.4 - blob: 0.0.5 - has-binary2: ~1.0.2 - checksum: c7291955c1af4b6c384c2642c2d10a4df0ca7b6acc5cb178dd4933bcb1522eccc3d89ffae6e6080ce760451378fce49db47af3fb9999cae08de310e75f3c29d6 - languageName: node - linkType: hard - -"engine.io@npm:~3.6.0": - version: 3.6.1 - resolution: "engine.io@npm:3.6.1" - dependencies: - accepts: ~1.3.4 - base64id: 2.0.0 - cookie: ~0.4.1 - debug: ~4.1.0 - engine.io-parser: ~2.2.0 - ws: ~7.4.2 - checksum: 7dd9eddc79aedf61a63141e6208ee89936c659445378f965bff6d5eb3e9cb4815aff735f2b1886487e2be51116a343e89d972ae5790bf2ac9fdcb2572baf8935 - languageName: node - linkType: hard - "enhanced-resolve@npm:^5.10.0": version: 5.10.0 resolution: "enhanced-resolve@npm:5.10.0" @@ -21295,6 +21166,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:~2.0": + version: 2.0.3 + resolution: "entities@npm:2.0.3" + checksum: 5a7899fcc622e0d76afdeafe4c58a6b40ae3a8ee4772e5825a648c11a2ca324a9a02515386f512e466baac4aeb551f3d3b79eaece5cd98369b9f8601be336b1a + languageName: node + linkType: hard + "entities@npm:~2.1.0": version: 2.1.0 resolution: "entities@npm:2.1.0" @@ -21348,7 +21226,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.2, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": +"es-abstract@npm:^1.19.0, es-abstract@npm:^1.19.5, es-abstract@npm:^1.20.4": version: 1.20.4 resolution: "es-abstract@npm:1.20.4" dependencies: @@ -21586,7 +21464,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.15.6": +"esbuild@npm:^0.15.6, esbuild@npm:~0.15.10": version: 0.15.18 resolution: "esbuild@npm:0.15.18" dependencies: @@ -21664,31 +21542,31 @@ __metadata: linkType: hard "esbuild@npm:^0.17.0": - version: 0.17.5 - resolution: "esbuild@npm:0.17.5" + version: 0.17.6 + resolution: "esbuild@npm:0.17.6" dependencies: - "@esbuild/android-arm": 0.17.5 - "@esbuild/android-arm64": 0.17.5 - "@esbuild/android-x64": 0.17.5 - "@esbuild/darwin-arm64": 0.17.5 - "@esbuild/darwin-x64": 0.17.5 - "@esbuild/freebsd-arm64": 0.17.5 - "@esbuild/freebsd-x64": 0.17.5 - "@esbuild/linux-arm": 0.17.5 - "@esbuild/linux-arm64": 0.17.5 - "@esbuild/linux-ia32": 0.17.5 - "@esbuild/linux-loong64": 0.17.5 - "@esbuild/linux-mips64el": 0.17.5 - "@esbuild/linux-ppc64": 0.17.5 - "@esbuild/linux-riscv64": 0.17.5 - "@esbuild/linux-s390x": 0.17.5 - "@esbuild/linux-x64": 0.17.5 - "@esbuild/netbsd-x64": 0.17.5 - "@esbuild/openbsd-x64": 0.17.5 - "@esbuild/sunos-x64": 0.17.5 - "@esbuild/win32-arm64": 0.17.5 - "@esbuild/win32-ia32": 0.17.5 - "@esbuild/win32-x64": 0.17.5 + "@esbuild/android-arm": 0.17.6 + "@esbuild/android-arm64": 0.17.6 + "@esbuild/android-x64": 0.17.6 + "@esbuild/darwin-arm64": 0.17.6 + "@esbuild/darwin-x64": 0.17.6 + "@esbuild/freebsd-arm64": 0.17.6 + "@esbuild/freebsd-x64": 0.17.6 + "@esbuild/linux-arm": 0.17.6 + "@esbuild/linux-arm64": 0.17.6 + "@esbuild/linux-ia32": 0.17.6 + "@esbuild/linux-loong64": 0.17.6 + "@esbuild/linux-mips64el": 0.17.6 + "@esbuild/linux-ppc64": 0.17.6 + "@esbuild/linux-riscv64": 0.17.6 + "@esbuild/linux-s390x": 0.17.6 + "@esbuild/linux-x64": 0.17.6 + "@esbuild/netbsd-x64": 0.17.6 + "@esbuild/openbsd-x64": 0.17.6 + "@esbuild/sunos-x64": 0.17.6 + "@esbuild/win32-arm64": 0.17.6 + "@esbuild/win32-ia32": 0.17.6 + "@esbuild/win32-x64": 0.17.6 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -21736,7 +21614,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 31829b46a0cad65f58d90d39b66fd32a2de820539dd8530199975e417aa0ecd63cfc340e402f4f4e9235906a1a05969ddac1d4ad1ba611a3f11c0f62516b9390 + checksum: 13c4c3bcaa7ff291810d2c8294a1eb997b4672c60a9285b32d8eafcbc552e4468e06efe9d1a15067f5cbd41adcb12ddb4362618845e2e916e437f281c9aa80ab languageName: node linkType: hard @@ -21844,23 +21722,26 @@ __metadata: languageName: node linkType: hard -"eslint-import-resolver-node@npm:^0.3.6": - version: 0.3.6 - resolution: "eslint-import-resolver-node@npm:0.3.6" +"eslint-import-resolver-node@npm:^0.3.7": + version: 0.3.7 + resolution: "eslint-import-resolver-node@npm:0.3.7" dependencies: debug: ^3.2.7 - resolve: ^1.20.0 - checksum: 6266733af1e112970e855a5bcc2d2058fb5ae16ad2a6d400705a86b29552b36131ffc5581b744c23d550de844206fb55e9193691619ee4dbf225c4bde526b1c8 + is-core-module: ^2.11.0 + resolve: ^1.22.1 + checksum: 3379aacf1d2c6952c1b9666c6fa5982c3023df695430b0d391c0029f6403a7775414873d90f397e98ba6245372b6c8960e16e74d9e4a3b0c0a4582f3bdbe3d6e languageName: node linkType: hard -"eslint-module-utils@npm:^2.1.1, eslint-module-utils@npm:^2.7.3": - version: 2.7.3 - resolution: "eslint-module-utils@npm:2.7.3" +"eslint-module-utils@npm:^2.7.4": + version: 2.7.4 + resolution: "eslint-module-utils@npm:2.7.4" dependencies: debug: ^3.2.7 - find-up: ^2.1.0 - checksum: 77048263f309167a1e6a1e1b896bfb5ddd1d3859b2e2abbd9c32c432aee13d610d46e6820b1ca81b37fba437cf423a404bc6649be64ace9148a3062d1886a678 + peerDependenciesMeta: + eslint: + optional: true + checksum: 5da13645daff145a5c922896b258f8bba560722c3767254e458d894ff5fbb505d6dfd945bffa932a5b0ae06714da2379bd41011c4c20d2d59cc83e23895360f7 languageName: node linkType: hard @@ -21890,25 +21771,27 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.25.4": - version: 2.26.0 - resolution: "eslint-plugin-import@npm:2.26.0" + version: 2.27.5 + resolution: "eslint-plugin-import@npm:2.27.5" dependencies: - array-includes: ^3.1.4 - array.prototype.flat: ^1.2.5 - debug: ^2.6.9 + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + array.prototype.flatmap: ^1.3.1 + debug: ^3.2.7 doctrine: ^2.1.0 - eslint-import-resolver-node: ^0.3.6 - eslint-module-utils: ^2.7.3 + eslint-import-resolver-node: ^0.3.7 + eslint-module-utils: ^2.7.4 has: ^1.0.3 - is-core-module: ^2.8.1 + is-core-module: ^2.11.0 is-glob: ^4.0.3 minimatch: ^3.1.2 - object.values: ^1.1.5 - resolve: ^1.22.0 + object.values: ^1.1.6 + resolve: ^1.22.1 + semver: ^6.3.0 tsconfig-paths: ^3.14.1 peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 0bf77ad80339554481eafa2b1967449e1f816b94c7a6f9614ce33fb4083c4e6c050f10d241dd50b4975d47922880a34de1e42ea9d8e6fd663ebb768baa67e655 + checksum: f500571a380167e25d72a4d925ef9a7aae8899eada57653e5f3051ec3d3c16d08271fcefe41a30a9a2f4fefc232f066253673ee4ea77b30dba65ae173dade85d languageName: node linkType: hard @@ -21955,21 +21838,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-monorepo@npm:^0.3.2": - version: 0.3.2 - resolution: "eslint-plugin-monorepo@npm:0.3.2" - dependencies: - eslint-module-utils: ^2.1.1 - get-monorepo-packages: ^1.1.0 - globby: ^7.1.1 - load-json-file: ^4.0.0 - minimatch: ^3.0.4 - parse-package-name: ^0.1.0 - path-is-inside: ^1.0.2 - checksum: b6f17efbc9e66aefbf7aacf9aa130bc8e729a6311c412d1b0026ce7d93361c10b0e6e4b10cf434f24ca9a8b2e891bc8e5b82e66dc9ccc5e782f9c18a989eca28 - languageName: node - linkType: hard - "eslint-plugin-notice@npm:^0.9.10": version: 0.9.10 resolution: "eslint-plugin-notice@npm:0.9.10" @@ -22018,13 +21886,13 @@ __metadata: linkType: hard "eslint-plugin-testing-library@npm:^5.9.1": - version: 5.10.0 - resolution: "eslint-plugin-testing-library@npm:5.10.0" + version: 5.10.1 + resolution: "eslint-plugin-testing-library@npm:5.10.1" dependencies: "@typescript-eslint/utils": ^5.43.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: 3278fc4683a99d24ac2b6d2ed0359db1b0509674350e4b9a958a226f57b4b90e070c02e1f4c2806da885d8025c1e8c952cb9a5e9751e69baac3d12cfe6804000 + checksum: fbc24ce8cbd03bee283ae520f023bd52f10d21fb25bd66c5a09a0e0ad17997bae559450438ce0b4fcc38b4e14b6802f18482c41d2bc72bf1a8e1a12a91766572 languageName: node linkType: hard @@ -22089,9 +21957,9 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.6.0": - version: 8.31.0 - resolution: "eslint@npm:8.31.0" +"eslint@npm:^8.33.0, eslint@npm:^8.6.0": + version: 8.33.0 + resolution: "eslint@npm:8.33.0" dependencies: "@eslint/eslintrc": ^1.4.1 "@humanwhocodes/config-array": ^0.11.8 @@ -22134,7 +22002,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 5e5688bb864edc6b12d165849994812eefa67fb3fc44bb26f53659b63edcd8bcc68389d27cc6cc9e5b79ee22f24b6f311fa3ed047bddcafdec7d84c1b5561e4f + checksum: 727e63ab8b7acf281442323c5971f6afdd5b656fbcebc4476cf54e35af51b2f180617433fc5e1952f0449ca3f43a905527f9407ea4b8a7ea7562fc9c3f278d4c languageName: node linkType: hard @@ -22359,6 +22227,7 @@ __metadata: "@backstage/plugin-kafka": "workspace:^" "@backstage/plugin-kubernetes": "workspace:^" "@backstage/plugin-lighthouse": "workspace:^" + "@backstage/plugin-microsoft-calendar": "workspace:^" "@backstage/plugin-newrelic": "workspace:^" "@backstage/plugin-newrelic-dashboard": "workspace:^" "@backstage/plugin-org": "workspace:^" @@ -22456,6 +22325,7 @@ __metadata: "@backstage/plugin-jenkins-backend": "workspace:^" "@backstage/plugin-kafka-backend": "workspace:^" "@backstage/plugin-kubernetes-backend": "workspace:^" + "@backstage/plugin-lighthouse-backend": "workspace:^" "@backstage/plugin-permission-backend": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" @@ -22555,13 +22425,6 @@ __metadata: languageName: node linkType: hard -"exif-parser@npm:^0.1.12": - version: 0.1.12 - resolution: "exif-parser@npm:0.1.12" - checksum: 6ba50cb9e0b45a6efa37e966a9582ecd171b5c5b3ef0c47542f2b862c521f70d2f656dde85b4d2a5dd8e1163486b09049f4c412e9c6176bfbda1654a5b2f021c - languageName: node - linkType: hard - "exit-on-epipe@npm:~1.0.1": version: 1.0.1 resolution: "exit-on-epipe@npm:1.0.1" @@ -22932,6 +22795,21 @@ __metadata: languageName: node linkType: hard +"fbjs@npm:^0.8.1": + version: 0.8.18 + resolution: "fbjs@npm:0.8.18" + dependencies: + core-js: ^1.0.0 + isomorphic-fetch: ^2.1.1 + loose-envify: ^1.0.0 + object-assign: ^4.1.0 + promise: ^7.1.1 + setimmediate: ^1.0.5 + ua-parser-js: ^0.7.30 + checksum: 668731b946a765908c9cbe51d5160f973abb78004b3d122587c3e930e3e1ddcc0ce2b17f2a8637dc9d733e149aa580f8d3035a35cc2d3bc78b78f1b19aab90e2 + languageName: node + linkType: hard + "fbjs@npm:^3.0.0": version: 3.0.0 resolution: "fbjs@npm:3.0.0" @@ -22992,13 +22870,6 @@ __metadata: languageName: node linkType: hard -"file-type@npm:^9.0.0": - version: 9.0.0 - resolution: "file-type@npm:9.0.0" - checksum: 9ea78b29c3762d967eb1e3e4f45e401388b6d252b12c217f78f5ea97556ff7e35e4c7255cab68810ac414d51b776bd4e83504c86f132c262a454251561189efa - languageName: node - linkType: hard - "file-uri-to-path@npm:1.0.0": version: 1.0.0 resolution: "file-uri-to-path@npm:1.0.0" @@ -23106,15 +22977,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^2.1.0": - version: 2.1.0 - resolution: "find-up@npm:2.1.0" - dependencies: - locate-path: ^2.0.0 - checksum: 43284fe4da09f89011f08e3c32cd38401e786b19226ea440b75386c1b12a4cb738c94969808d53a84f564ede22f732c8409e3cfc3f7fb5b5c32378ad0bbf28bd - languageName: node - linkType: hard - "find-up@npm:^3.0.0": version: 3.0.0 resolution: "find-up@npm:3.0.0" @@ -23689,16 +23551,6 @@ __metadata: languageName: node linkType: hard -"get-monorepo-packages@npm:^1.1.0": - version: 1.2.0 - resolution: "get-monorepo-packages@npm:1.2.0" - dependencies: - globby: ^7.1.1 - load-json-file: ^4.0.0 - checksum: f9321c11b8e11f02138758db6589d8ab8b7e1b05e78cac92493b635faea10aa100c20fe40f2cf110c82ec100c118c6c131dff4c65d32a721c617dc2928f7b277 - languageName: node - linkType: hard - "get-package-type@npm:^0.1.0": version: 0.1.0 resolution: "get-package-type@npm:0.1.0" @@ -23746,6 +23598,13 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.4.0": + version: 4.4.0 + resolution: "get-tsconfig@npm:4.4.0" + checksum: e193558b4f0c84c81ae9688cf5b9950dc0b341e44f91b002713fd0c37cfb73108e1cd9998ed540bcc423f193fde32cc58a15e99dd469f5158a2eb4a148611176 + languageName: node + linkType: hard + "getopts@npm:2.3.0": version: 2.3.0 resolution: "getopts@npm:2.3.0" @@ -23836,7 +23695,20 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": +"glob@npm:8.0.3": + version: 8.0.3 + resolution: "glob@npm:8.0.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^5.0.1 + once: ^1.3.0 + checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + languageName: node + linkType: hard + +"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -23851,15 +23723,15 @@ __metadata: linkType: hard "glob@npm:^8.0.0, glob@npm:^8.0.1, glob@npm:^8.0.3": - version: 8.0.3 - resolution: "glob@npm:8.0.3" + version: 8.1.0 + resolution: "glob@npm:8.1.0" dependencies: fs.realpath: ^1.0.0 inflight: ^1.0.4 inherits: 2 minimatch: ^5.0.1 once: ^1.3.0 - checksum: 50bcdea19d8e79d8de5f460b1939ffc2b3299eac28deb502093fdca22a78efebc03e66bf54f0abc3d3d07d8134d19a32850288b7440d77e072aa55f9d33b18c5 + checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47 languageName: node linkType: hard @@ -23906,16 +23778,6 @@ __metadata: languageName: node linkType: hard -"global@npm:~4.4.0": - version: 4.4.0 - resolution: "global@npm:4.4.0" - dependencies: - min-document: ^2.19.0 - process: ^0.11.10 - checksum: 9c057557c8f5a5bcfbeb9378ba4fe2255d04679452be504608dd5f13b54edf79f7be1db1031ea06a4ec6edd3b9f5f17d2d172fb47e6c69dae57fd84b7e72b77f - languageName: node - linkType: hard - "globals@npm:^11.1.0, globals@npm:^11.12.0": version: 11.12.0 resolution: "globals@npm:11.12.0" @@ -23955,17 +23817,12 @@ __metadata: languageName: node linkType: hard -"globby@npm:^7.1.1": - version: 7.1.1 - resolution: "globby@npm:7.1.1" +"good-listener@npm:^1.2.2": + version: 1.2.2 + resolution: "good-listener@npm:1.2.2" dependencies: - array-union: ^1.0.1 - dir-glob: ^2.0.0 - glob: ^7.1.2 - ignore: ^3.3.5 - pify: ^3.0.0 - slash: ^1.0.0 - checksum: f0eba08a08ae7c98149a4411661c0bf08c4717d81e6f355cf624fb01880b249737eb8e951bf86124cb3af8ea1c793c0a9d363ed5cdec99bb2c6b68f8a323025f + delegate: ^3.1.2 + checksum: f39fb82c4e41524f56104cfd2d7aef1a88e72f3f75139115fbdf98cc7d844e0c1b39218b2e83438c6188727bf904ed78c7f0f2feff67b32833bc3af7f0202b33 languageName: node linkType: hard @@ -24181,6 +24038,27 @@ __metadata: languageName: node linkType: hard +"graphql-voyager@npm:^1.0.0-rc.31": + version: 1.0.0-rc.31 + resolution: "graphql-voyager@npm:1.0.0-rc.31" + dependencies: + "@f/animate": ^1.0.1 + "@material-ui/core": ^3.9.3 + classnames: ^2.2.6 + clipboard: ^2.0.4 + commonmark: ^0.29.0 + lodash: ^4.17.10 + prop-types: ^15.7.2 + svg-pan-zoom: ^3.6.0 + viz.js: 2.1.2 + peerDependencies: + graphql: ">=14.0.0" + react: ">=15.4.2" + react-dom: ">=15.4.2" + checksum: 80e826eeb42d286540447723ea35a463a3a155287914a45e24b69f31617d8ca74c0c43bdaa64123bf4ed046e68f7e31feca7661c06288551040f3e5b96c48fed + languageName: node + linkType: hard + "graphql-ws@npm:5.11.2, graphql-ws@npm:^5.4.1, graphql-ws@npm:^5.9.0": version: 5.11.2 resolution: "graphql-ws@npm:5.11.2" @@ -24311,22 +24189,6 @@ __metadata: languageName: node linkType: hard -"has-binary2@npm:~1.0.2": - version: 1.0.3 - resolution: "has-binary2@npm:1.0.3" - dependencies: - isarray: 2.0.1 - checksum: 9183a617830b1f50b35961fbe39278cc43089cdac7c47a7f16aafb9d8190553fa360e5da34a479d6c988db40ea10aa02bca5abcb2451b5fc3924ae2f013ffdab - languageName: node - linkType: hard - -"has-cors@npm:1.1.0": - version: 1.1.0 - resolution: "has-cors@npm:1.1.0" - checksum: 549ce94113fd23895b22d71ade9809918577b8558cd4d701fe79045d8b1d58d87eba870260b28f6a3229be933a691c55653afd496d0fc52e98fd2ff577f01197 - languageName: node - linkType: hard - "has-flag@npm:^3.0.0": version: 3.0.0 resolution: "has-flag@npm:3.0.0" @@ -24503,19 +24365,14 @@ __metadata: languageName: node linkType: hard -"hogan.js@npm:^3.0.2": - version: 3.0.2 - resolution: "hogan.js@npm:3.0.2" - dependencies: - mkdirp: 0.3.0 - nopt: 1.0.10 - bin: - hulk: ./bin/hulk - checksum: c7bbff84faa9ca265c39f4a2100546ba0388fcc9c5bac8526f488592ce3fcaa042eba6ac25db277f4478ec3855b9bc28ce59acffbf6e8a28d45a17df7590c6aa +"hoist-non-react-statics@npm:^2.3.1": + version: 2.5.5 + resolution: "hoist-non-react-statics@npm:2.5.5" + checksum: ee2d05e5c7e1398ad84a15b0327f66bd78f38a8e0015e852f954b36434e32eb7e942d5357505020a3a1147f247b165bf1e69d72393e3accab67cafdafeb86230 languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": +"hoist-non-react-statics@npm:^3.0.0, hoist-non-react-statics@npm:^3.2.1, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" dependencies: @@ -24566,6 +24423,13 @@ __metadata: languageName: node linkType: hard +"hpagent@npm:^1.2.0": + version: 1.2.0 + resolution: "hpagent@npm:1.2.0" + checksum: b029da695edae438cee4da2a437386f9db4ac27b3ceb7306d02e1b586c9c194741ed2e943c8a222e0cfefaf27ee3f863aca7ba1721b0950a2a19bf25bc0d85e2 + languageName: node + linkType: hard + "html-encoding-sniffer@npm:^2.0.1": version: 2.0.1 resolution: "html-encoding-sniffer@npm:2.0.1" @@ -24655,9 +24519,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard @@ -24942,13 +24806,6 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^3.3.5": - version: 3.3.10 - resolution: "ignore@npm:3.3.10" - checksum: 23e8cc776e367b56615ab21b78decf973a35dfca5522b39d9b47643d8168473b0d1f18dd1321a1bab466a12ea11a2411903f3b21644f4d5461ee0711ec8678bd - languageName: node - linkType: hard - "ignore@npm:^5.1.4, ignore@npm:^5.2.0": version: 5.2.0 resolution: "ignore@npm:5.2.0" @@ -24956,15 +24813,6 @@ __metadata: languageName: node linkType: hard -"image-size@npm:^0.7.2": - version: 0.7.5 - resolution: "image-size@npm:0.7.5" - bin: - image-size: bin/image-size.js - checksum: f88860c9d9b5c8ad00d3de9d6f5ba105bda5a5024bfb6b90559a075a4b838ed4f5d3cba14edf0f18fe5d75df596a172b52feca43848e11c34f31f4df2c88a011 - languageName: node - linkType: hard - "immer@npm:9.0.7": version: 9.0.7 resolution: "immer@npm:9.0.7" @@ -25054,6 +24902,15 @@ __metadata: languageName: node linkType: hard +"indefinite-observable@npm:^1.0.1": + version: 1.0.2 + resolution: "indefinite-observable@npm:1.0.2" + dependencies: + symbol-observable: 1.2.0 + checksum: 69a337967f48fca18989f9d68ad98c7220ed9b499bf00330ff72669a9583cb7f8e82f801da10720f720edf1313f427c77ce793350bdc413c952cec8ce112fc12 + languageName: node + linkType: hard + "indefinite-observable@npm:^2.0.1": version: 2.0.1 resolution: "indefinite-observable@npm:2.0.1" @@ -25070,13 +24927,6 @@ __metadata: languageName: node linkType: hard -"indexof@npm:0.0.1": - version: 0.0.1 - resolution: "indexof@npm:0.0.1" - checksum: 0fb04e8b147b8585d981a6df1564f25bb3678d6fa74e33e5cecc1464b10f78e15e8ef6bb688f135fe5c2844a128fac8a7831cbe5adc81fdcf12681b093dfcc25 - languageName: node - linkType: hard - "infer-owner@npm:^1.0.4": version: 1.0.4 resolution: "infer-owner@npm:1.0.4" @@ -25248,20 +25098,20 @@ __metadata: languageName: node linkType: hard -"ioredis@npm:^5.2.4": - version: 5.2.4 - resolution: "ioredis@npm:5.2.4" +"ioredis@npm:^5.3.0": + version: 5.3.0 + resolution: "ioredis@npm:5.3.0" dependencies: "@ioredis/commands": ^1.1.1 cluster-key-slot: ^1.1.0 debug: ^4.3.4 - denque: ^2.0.1 + denque: ^2.1.0 lodash.defaults: ^4.2.0 lodash.isarguments: ^3.1.0 redis-errors: ^1.2.0 redis-parser: ^3.0.0 standard-as-callback: ^2.1.0 - checksum: c3a7df407a41ae516bede8b6db853c568198b13fe4a4785f66be5cd541087121b9d45fb9a6b1b6a5fb668c29ce52ab4685642b994803bdfa0a35f794ea8ef7ae + checksum: d3a1fd8f1b5d9ce6d4b7dd083773dbe0936ea3d1f55f07d36daa3d0b59c4636e95640f90bc003a08bc900a9803307e7d7e191817a2c2970696e204dae6f3dc35 languageName: node linkType: hard @@ -25452,12 +25302,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.1.0, is-core-module@npm:^2.8.1, is-core-module@npm:^2.9.0": - version: 2.10.0 - resolution: "is-core-module@npm:2.10.0" +"is-core-module@npm:^2.1.0, is-core-module@npm:^2.11.0, is-core-module@npm:^2.9.0": + version: 2.11.0 + resolution: "is-core-module@npm:2.11.0" dependencies: has: ^1.0.3 - checksum: 0f3f77811f430af3256fa7bbc806f9639534b140f8ee69476f632c3e1eb4e28a38be0b9d1b8ecf596179c841b53576129279df95e7051d694dac4ceb6f967593 + checksum: f96fd490c6b48eb4f6d10ba815c6ef13f410b0ba6f7eb8577af51697de523e5f2cd9de1c441b51d27251bf0e4aebc936545e33a5d26d5d51f28d25698d4a8bab languageName: node linkType: hard @@ -25523,13 +25373,6 @@ __metadata: languageName: node linkType: hard -"is-function@npm:^1.0.1": - version: 1.0.2 - resolution: "is-function@npm:1.0.2" - checksum: 7d564562e07b4b51359547d3ccc10fb93bb392fd1b8177ae2601ee4982a0ece86d952323fc172a9000743a3971f09689495ab78a1d49a9b14fc97a7e28521dc0 - languageName: node - linkType: hard - "is-generator-fn@npm:^2.0.0": version: 2.1.0 resolution: "is-generator-fn@npm:2.1.0" @@ -25820,6 +25663,13 @@ __metadata: languageName: node linkType: hard +"is-stream@npm:^1.0.1": + version: 1.1.0 + resolution: "is-stream@npm:1.1.0" + checksum: 063c6bec9d5647aa6d42108d4c59723d2bd4ae42135a2d4db6eadbd49b7ea05b750fd69d279e5c7c45cf9da753ad2c00d8978be354d65aa9f6bb434969c6a2ae + languageName: node + linkType: hard + "is-stream@npm:^2.0.0": version: 2.0.1 resolution: "is-stream@npm:2.0.1" @@ -25962,13 +25812,6 @@ __metadata: languageName: node linkType: hard -"isarray@npm:2.0.1": - version: 2.0.1 - resolution: "isarray@npm:2.0.1" - checksum: a0521973213019b82889f028a41528ce7a3f103a710357b6875066202ee5a1fa9ae4135f915f3be9160b8c7a3ae4b39b073b804da3b58fa6b72f8b4b1e3dfef5 - languageName: node - linkType: hard - "isarray@npm:^1.0.0, isarray@npm:~1.0.0": version: 1.0.0 resolution: "isarray@npm:1.0.0" @@ -26022,6 +25865,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-fetch@npm:^2.1.1": + version: 2.2.1 + resolution: "isomorphic-fetch@npm:2.2.1" + dependencies: + node-fetch: ^1.0.1 + whatwg-fetch: ">=0.10.0" + checksum: bb5daa7c3785d6742f4379a81e55b549a469503f7c9bf9411b48592e86632cf5e8fe8ea878dba185c0f33eb7c510c23abdeb55aebfdf5d3c70f031ced68c5424 + languageName: node + linkType: hard + "isomorphic-fetch@npm:^3.0.0": version: 3.0.0 resolution: "isomorphic-fetch@npm:3.0.0" @@ -26732,20 +26585,6 @@ __metadata: languageName: node linkType: hard -"jimp@npm:^0.10.3": - version: 0.10.3 - resolution: "jimp@npm:0.10.3" - dependencies: - "@babel/runtime": ^7.7.2 - "@jimp/custom": ^0.10.3 - "@jimp/plugins": ^0.10.3 - "@jimp/types": ^0.10.3 - core-js: ^3.4.1 - regenerator-runtime: ^0.13.3 - checksum: ace7d9d76c2802e26392603c1fdfc988e7c468941ac127405f6752db9b5c89e1e27f202f96b764eede001ac245be0b46f52bb87eb91a42374027050568a7e816 - languageName: node - linkType: hard - "jju@npm:~1.4.0": version: 1.4.0 resolution: "jju@npm:1.4.0" @@ -26781,9 +26620,9 @@ __metadata: linkType: hard "jose@npm:^4.10.0, jose@npm:^4.6.0": - version: 4.11.2 - resolution: "jose@npm:4.11.2" - checksum: bc9b2271c31683603857b2fd2903afa29f826fffd4bcefc0845355ed86995def87eaadf502033207996109d76698c912e5a986e279326d9629321a50504fe466 + version: 4.11.4 + resolution: "jose@npm:4.11.4" + checksum: ab870d61e3721cfa1059b1a79cfc2fce06586c8afd4164362e1725934a635191bd938893ebdfac55a0811efbe9b6fd650bbf82d36d87e8a0b7cb4b0379328dab languageName: node linkType: hard @@ -26794,20 +26633,6 @@ __metadata: languageName: node linkType: hard -"jpeg-js@npm:^0.3.4": - version: 0.3.7 - resolution: "jpeg-js@npm:0.3.7" - checksum: 85a1ab09fe696fdd7b94ee077f1b8d1de307ffd7a83c0c45cc5cc56b0d7b47e561b92f6f090165648387875d674ba3076e3fedf395d5be4ef46760b6ebc804fe - languageName: node - linkType: hard - -"js-base64@npm:^2.5.1": - version: 2.6.4 - resolution: "js-base64@npm:2.6.4" - checksum: 5f4084078d6c46f8529741d110df84b14fac3276b903760c21fa8cc8521370d607325dfe1c1a9fbbeaae1ff8e602665aaeef1362427d8fef704f9e3659472ce8 - languageName: node - linkType: hard - "js-base64@npm:^3.6.0": version: 3.7.4 resolution: "js-base64@npm:3.7.4" @@ -27092,13 +26917,6 @@ __metadata: languageName: node linkType: hard -"json-parse-better-errors@npm:^1.0.1": - version: 1.0.2 - resolution: "json-parse-better-errors@npm:1.0.2" - checksum: ff2b5ba2a70e88fd97a3cb28c1840144c5ce8fae9cbeeddba15afa333a5c407cf0e42300cd0a2885dbb055227fe68d405070faad941beeffbfde9cf3b2c78c5d - languageName: node - linkType: hard - "json-parse-even-better-errors@npm:^2.3.0, json-parse-even-better-errors@npm:^2.3.1": version: 2.3.1 resolution: "json-parse-even-better-errors@npm:2.3.1" @@ -27380,6 +27198,46 @@ __metadata: languageName: node linkType: hard +"jss-camel-case@npm:^6.0.0": + version: 6.1.0 + resolution: "jss-camel-case@npm:6.1.0" + dependencies: + hyphenate-style-name: ^1.0.2 + peerDependencies: + jss: ^9.7.0 + checksum: f20ad892cddc30241b5127d648233b513ce57b2a6ed2f710cd995510f8d06e1418cd8f6e8e50dc6bd60b2e8a35159bfdeb40143938e0f2cdc19fd39279953789 + languageName: node + linkType: hard + +"jss-default-unit@npm:^8.0.2": + version: 8.0.2 + resolution: "jss-default-unit@npm:8.0.2" + peerDependencies: + jss: ^9.4.0 + checksum: 5277c5ccc3d56f5c137d6d65f0fc36d15eb22ef08b5949e887ee75e9f4f25197e25f2a99706b70a2828cee010fd8ed7484fb1bb2086fe327f2b24b1bdcc22abb + languageName: node + linkType: hard + +"jss-global@npm:^3.0.0": + version: 3.0.0 + resolution: "jss-global@npm:3.0.0" + peerDependencies: + jss: ^9.0.0 + checksum: e3fa80d8251ba5f183d9b0b4416d64e8f5d285cfdb595cc600daf1a1366b67bca573939bb71d98b6596bf4d6f2c95711cf53a358af3d63cd7945dbb434c6547b + languageName: node + linkType: hard + +"jss-nested@npm:^6.0.1": + version: 6.0.1 + resolution: "jss-nested@npm:6.0.1" + dependencies: + warning: ^3.0.0 + peerDependencies: + jss: ^9.0.0 + checksum: 437bdacc559be0b4b5bc1faa2bc77b5c6cf14733fefbf73a34bb7335786b9f08e4e79b3d73cf83b386959adcd8fa9d725877912e96d9a0921ed38baa1a69b8d9 + languageName: node + linkType: hard + "jss-plugin-camel-case@npm:^10.5.1": version: 10.6.0 resolution: "jss-plugin-camel-case@npm:10.6.0" @@ -27454,6 +27312,26 @@ __metadata: languageName: node linkType: hard +"jss-props-sort@npm:^6.0.0": + version: 6.0.0 + resolution: "jss-props-sort@npm:6.0.0" + peerDependencies: + jss: ^9.0.0 + checksum: 82a04f625a2f2b3a71b2fcb00b1ed0478137c83dc47c323d24c7ea88d08c9ea295b061f99cf264db133fef3435366d6da594724f7713e0415dc50b4eff2aeb53 + languageName: node + linkType: hard + +"jss-vendor-prefixer@npm:^7.0.0": + version: 7.0.0 + resolution: "jss-vendor-prefixer@npm:7.0.0" + dependencies: + css-vendor: ^0.3.8 + peerDependencies: + jss: ^9.0.0 + checksum: 8ec3608711833e79da7ccfffd8177e752f16093589fa28d3a24ec19e6588fbc6a07cc5cacf59ef4c111ab1d0fb72e07b88cb3444eb8c0c6ed4cc8107da984633 + languageName: node + linkType: hard + "jss@npm:10.6.0": version: 10.6.0 resolution: "jss@npm:10.6.0" @@ -27479,6 +27357,17 @@ __metadata: languageName: node linkType: hard +"jss@npm:^9.8.7": + version: 9.8.7 + resolution: "jss@npm:9.8.7" + dependencies: + is-in-browser: ^1.1.3 + symbol-observable: ^1.1.0 + warning: ^3.0.0 + checksum: ebb264cc893fb8c17a0277875947f8f72e01f5be991bf7f61a39abb861e1276e75ee402fdd2be9ce827af839a1a08bd81ad86a4e108d57fd7d7ebb2361837a53 + languageName: node + linkType: hard + "jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.3": version: 3.3.3 resolution: "jsx-ast-utils@npm:3.3.3" @@ -27820,8 +27709,8 @@ __metadata: linkType: hard "lint-staged@npm:^13.0.0": - version: 13.1.0 - resolution: "lint-staged@npm:13.1.0" + version: 13.1.1 + resolution: "lint-staged@npm:13.1.1" dependencies: cli-truncate: ^3.1.0 colorette: ^2.0.19 @@ -27838,7 +27727,7 @@ __metadata: yaml: ^2.1.3 bin: lint-staged: bin/lint-staged.js - checksum: adf20c4ca9285c4a93b06598b970d71b04cfe58a1a4c9006f753b83e02c1c622d1866c32a4f1e7e29a98091c501eac3345f7678af247b4f97d5be88b3d8727c1 + checksum: 8e5093c7e982a2f6d6449927a40156a812644479df1d2760aee8bf05df3a314e022d8f7e275e57fd61769ee57e3cf7b062ed3c6e4934a63848300b877e269daa languageName: node linkType: hard @@ -27905,22 +27794,6 @@ __metadata: languageName: node linkType: hard -"load-bmfont@npm:^1.3.1, load-bmfont@npm:^1.4.0": - version: 1.4.1 - resolution: "load-bmfont@npm:1.4.1" - dependencies: - buffer-equal: 0.0.1 - mime: ^1.3.4 - parse-bmfont-ascii: ^1.0.3 - parse-bmfont-binary: ^1.0.5 - parse-bmfont-xml: ^1.1.4 - phin: ^2.9.1 - xhr: ^2.0.1 - xtend: ^4.0.0 - checksum: 688d932fb0dc4c9333747736ccd926261f0b91734b7bdb6ff24f8659ef068a0f0b2278084b208851afac0beec79af7bd6664fe2ed5b6c5e1db88755fc25f785e - languageName: node - linkType: hard - "load-json-file@npm:^1.0.0": version: 1.1.0 resolution: "load-json-file@npm:1.1.0" @@ -27934,18 +27807,6 @@ __metadata: languageName: node linkType: hard -"load-json-file@npm:^4.0.0": - version: 4.0.0 - resolution: "load-json-file@npm:4.0.0" - dependencies: - graceful-fs: ^4.1.2 - parse-json: ^4.0.0 - pify: ^3.0.0 - strip-bom: ^3.0.0 - checksum: 8f5d6d93ba64a9620445ee9bde4d98b1eac32cf6c8c2d20d44abfa41a6945e7969456ab5f1ca2fb06ee32e206c9769a20eec7002fe290de462e8c884b6b8b356 - languageName: node - linkType: hard - "load-yaml-file@npm:^0.2.0": version: 0.2.0 resolution: "load-yaml-file@npm:0.2.0" @@ -27994,16 +27855,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^2.0.0": - version: 2.0.0 - resolution: "locate-path@npm:2.0.0" - dependencies: - p-locate: ^2.0.0 - path-exists: ^3.0.0 - checksum: 02d581edbbbb0fa292e28d96b7de36b5b62c2fa8b5a7e82638ebb33afa74284acf022d3b1e9ae10e3ffb7658fbc49163fcd5e76e7d1baaa7801c3e05a81da755 - languageName: node - linkType: hard - "locate-path@npm:^3.0.0": version: 3.0.0 resolution: "locate-path@npm:3.0.0" @@ -28235,7 +28086,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.13, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": +"lodash@npm:4.17.21, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -28792,7 +28643,7 @@ __metadata: languageName: node linkType: hard -"mdurl@npm:^1.0.0, mdurl@npm:^1.0.1": +"mdurl@npm:^1.0.0, mdurl@npm:^1.0.1, mdurl@npm:~1.0.1": version: 1.0.1 resolution: "mdurl@npm:1.0.1" checksum: 71731ecba943926bfbf9f9b51e28b5945f9411c4eda80894221b47cc105afa43ba2da820732b436f0798fd3edbbffcd1fc1415843c41a87fea08a41cc1e3d02b @@ -28904,13 +28755,6 @@ __metadata: languageName: node linkType: hard -"merge@npm:^1.2.1": - version: 1.2.1 - resolution: "merge@npm:1.2.1" - checksum: 2298c4fdcf64561f320b92338681f7ffcafafb579a6e294066ae3e7bd10ae25df363903d2f028072733b9f79a1f75d2b999aef98ad5d73de13641da39cda0913 - languageName: node - linkType: hard - "meros@npm:1.2.1, meros@npm:^1.1.4": version: 1.2.1 resolution: "meros@npm:1.2.1" @@ -28923,6 +28767,13 @@ __metadata: languageName: node linkType: hard +"meta-png@npm:1.0.5": + version: 1.0.5 + resolution: "meta-png@npm:1.0.5" + checksum: b8c92a696d5e78ef7f0ab53eb9039f108ee0c55cdac9d70e92e5fe2187b090176c0489426d58e594c7d1096481dac37913dd1265f28dfa39926db4d702a5e21d + languageName: node + linkType: hard + "methods@npm:^1.0.0, methods@npm:^1.1.2, methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" @@ -29312,7 +29163,7 @@ __metadata: languageName: node linkType: hard -"mime@npm:1.6.0, mime@npm:^1.3.4": +"mime@npm:1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" bin: @@ -29374,15 +29225,6 @@ __metadata: languageName: node linkType: hard -"min-document@npm:^2.19.0": - version: 2.19.0 - resolution: "min-document@npm:2.19.0" - dependencies: - dom-walk: ^0.1.0 - checksum: da6437562ea2228041542a2384528e74e22d1daa1a4ec439c165abf0b9d8a63e17e3b8a6dc6e0c731845e85301198730426932a0e813d23f932ca668340c9623 - languageName: node - linkType: hard - "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -29453,7 +29295,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": +"minimist@npm:>=1.2.2, minimist@npm:^1.2.0, minimist@npm:^1.2.3, minimist@npm:^1.2.5, minimist@npm:^1.2.6, minimist@npm:^1.2.7": version: 1.2.7 resolution: "minimist@npm:1.2.7" checksum: 7346574a1038ca23c32e02252f603801f09384dd1d78b69a943a4e8c2c28730b80e96193882d3d3b22a063445f460e48316b29b8a25addca2d7e5e8f75478bec @@ -29598,24 +29440,6 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:0.3.0": - version: 0.3.0 - resolution: "mkdirp@npm:0.3.0" - checksum: 3ec9cda8bd89b64892728e5092bc79e88382e444d4bbde040c2fb8d7034dc70682cfdd729e93241fd5243d2397324c420ef68c717d806db51bf96c0fc80f4b1d - languageName: node - linkType: hard - -"mkdirp@npm:^0.5.1": - version: 0.5.5 - resolution: "mkdirp@npm:0.5.5" - dependencies: - minimist: ^1.2.5 - bin: - mkdirp: bin/cmd.js - checksum: 3bce20ea525f9477befe458ab85284b0b66c8dc3812f94155af07c827175948cdd8114852ac6c6d82009b13c1048c37f6d98743eb019651ee25c39acc8aabe7d - languageName: node - linkType: hard - "mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" @@ -29652,6 +29476,15 @@ __metadata: languageName: node linkType: hard +"move-file@npm:2.1.0": + version: 2.1.0 + resolution: "move-file@npm:2.1.0" + dependencies: + path-exists: ^4.0.0 + checksum: 2b92bbe047a302b593fcb2c0bf1131bb090ec80b3264569fc80d782c8ff829eecc13573943fa4d804c9747dec612ef2d1e84a5cfcf29cbc64a69ffcbb7ea09b3 + languageName: node + linkType: hard + "mri@npm:1.1.4": version: 1.1.4 resolution: "mri@npm:1.1.4" @@ -29958,6 +29791,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^5.0.0": + version: 5.1.0 + resolution: "node-addon-api@npm:5.1.0" + dependencies: + node-gyp: latest + checksum: 2508bd2d2981945406243a7bd31362fc7af8b70b8b4d65f869c61731800058fb818cc2fd36c8eac714ddd0e568cc85becf5e165cebbdf7b5024d5151bbc75ea1 + languageName: node + linkType: hard + "node-cache@npm:^5.1.2": version: 5.1.2 resolution: "node-cache@npm:5.1.2" @@ -29983,7 +29825,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:2.6.7, node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": +"node-fetch@npm:2.6.7": version: 2.6.7 resolution: "node-fetch@npm:2.6.7" dependencies: @@ -29997,6 +29839,30 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^1.0.1": + version: 1.7.3 + resolution: "node-fetch@npm:1.7.3" + dependencies: + encoding: ^0.1.11 + is-stream: ^1.0.1 + checksum: 3bb0528c05d541316ebe52770d71ee25a6dce334df4231fd55df41a644143e07f068637488c18a5b0c43f05041dbd3346752f9e19b50df50569a802484544d5b + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": + version: 2.6.9 + resolution: "node-fetch@npm:2.6.9" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: acb04f9ce7224965b2b59e71b33c639794d8991efd73855b0b250921382b38331ffc9d61bce502571f6cc6e11a8905ca9b1b6d4aeb586ab093e2756a1fd190d0 + languageName: node + linkType: hard + "node-forge@npm:^1, node-forge@npm:^1.3.1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -30129,17 +29995,6 @@ __metadata: languageName: node linkType: hard -"nopt@npm:1.0.10, nopt@npm:~1.0.10": - version: 1.0.10 - resolution: "nopt@npm:1.0.10" - dependencies: - abbrev: 1 - bin: - nopt: ./bin/nopt.js - checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 - languageName: node - linkType: hard - "nopt@npm:^5.0.0": version: 5.0.0 resolution: "nopt@npm:5.0.0" @@ -30162,6 +30017,17 @@ __metadata: languageName: node linkType: hard +"nopt@npm:~1.0.10": + version: 1.0.10 + resolution: "nopt@npm:1.0.10" + dependencies: + abbrev: 1 + bin: + nopt: ./bin/nopt.js + checksum: f62575aceaa3be43f365bf37a596b89bbac2e796b001b6d2e2a85c2140a4e378ff919e2753ccba959c4fd344776fc88c29b393bc167fa939fb1513f126f4cd45 + languageName: node + linkType: hard + "normalize-package-data@npm:^2.3.2, normalize-package-data@npm:^2.5.0": version: 2.5.0 resolution: "normalize-package-data@npm:2.5.0" @@ -30190,6 +30056,13 @@ __metadata: languageName: node linkType: hard +"normalize-scroll-left@npm:^0.1.2": + version: 0.1.2 + resolution: "normalize-scroll-left@npm:0.1.2" + checksum: 817d5a659ba6f14f458cd03a5a0f98ec2a9d7e6c63c160f2db164827b87bb77c0237752890a18d11054fe628907493c5f4d8914907585ec9fbba3de26d2a6815 + languageName: node + linkType: hard + "normalize-url@npm:^6.0.1": version: 6.1.0 resolution: "normalize-url@npm:6.1.0" @@ -30321,7 +30194,7 @@ __metadata: languageName: node linkType: hard -"npmlog@npm:^4.0.1, npmlog@npm:^4.1.2": +"npmlog@npm:^4.1.2": version: 4.1.2 resolution: "npmlog@npm:4.1.2" dependencies: @@ -30508,7 +30381,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.5, object.values@npm:^1.1.6": +"object.values@npm:^1.1.6": version: 1.1.6 resolution: "object.values@npm:1.1.6" dependencies: @@ -30558,13 +30431,6 @@ __metadata: languageName: node linkType: hard -"omggif@npm:^1.0.9": - version: 1.0.10 - resolution: "omggif@npm:1.0.10" - checksum: 15102e46b6fa0fba32d7e948f702623cdc3cdcdfd64b2d33c6e29a61f366ffd0f250da55d66f5217dce5b93ba9c67763fa998652791a5c7f2201a3bde2c4db45 - languageName: node - linkType: hard - "on-finished@npm:2.4.1, on-finished@npm:^2.3.0": version: 2.4.1 resolution: "on-finished@npm:2.4.1" @@ -30804,15 +30670,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^1.1.0": - version: 1.3.0 - resolution: "p-limit@npm:1.3.0" - dependencies: - p-try: ^1.0.0 - checksum: 281c1c0b8c82e1ac9f81acd72a2e35d402bf572e09721ce5520164e9de07d8274451378a3470707179ad13240535558f4b277f02405ad752e08c7d5b0d54fbfd - languageName: node - linkType: hard - "p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -30831,15 +30688,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^2.0.0": - version: 2.0.0 - resolution: "p-locate@npm:2.0.0" - dependencies: - p-limit: ^1.1.0 - checksum: e2dceb9b49b96d5513d90f715780f6f4972f46987dc32a0e18bc6c3fc74a1a5d73ec5f81b1398af5e58b99ea1ad03fd41e9181c01fa81b4af2833958696e3081 - languageName: node - linkType: hard - "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -30922,13 +30770,6 @@ __metadata: languageName: node linkType: hard -"p-try@npm:^1.0.0": - version: 1.0.0 - resolution: "p-try@npm:1.0.0" - checksum: 3b5303f77eb7722144154288bfd96f799f8ff3e2b2b39330efe38db5dd359e4fb27012464cd85cb0a76e9b7edd1b443568cb3192c22e7cffc34989df0bafd605 - languageName: node - linkType: hard - "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -30972,7 +30813,7 @@ __metadata: languageName: node linkType: hard -"pako@npm:^1.0.10, pako@npm:^1.0.5, pako@npm:~1.0.5": +"pako@npm:^1.0.10, pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" checksum: 1be2bfa1f807608c7538afa15d6f25baa523c30ec870a3228a89579e474a4d992f4293859524e46d5d87fd30fa17c5edf34dbef0671251d9749820b488660b16 @@ -31019,30 +30860,6 @@ __metadata: languageName: node linkType: hard -"parse-bmfont-ascii@npm:^1.0.3": - version: 1.0.6 - resolution: "parse-bmfont-ascii@npm:1.0.6" - checksum: de3f6671f183c3e9d64bb4812b0407693b5fd0d24e9d16b2e106bb9eef809d64a6cc061f39ca29bb10c5c2e47e241e91b7aeefa587391fff7ccb27ab9db5012e - languageName: node - linkType: hard - -"parse-bmfont-binary@npm:^1.0.5": - version: 1.0.6 - resolution: "parse-bmfont-binary@npm:1.0.6" - checksum: ca37fb1e92f5941fddc5342b45857fafd27f00d2bd5fa44dd504bec6faeab97536c95ad45260c2dd5fc4c63de71e525663d3cdac09d038cbca803d97c669add5 - languageName: node - linkType: hard - -"parse-bmfont-xml@npm:^1.1.4": - version: 1.1.4 - resolution: "parse-bmfont-xml@npm:1.1.4" - dependencies: - xml-parse-from-string: ^1.0.0 - xml2js: ^0.4.5 - checksum: 879e5435be44f22b8c4934e2e1d2754a6d90a9ddb16309360daff965e1428d877b673f3d1fafaab4fef437c912a0db9f85545e0dd375ec62df7d4d328450d257 - languageName: node - linkType: hard - "parse-conflict-json@npm:^2.0.1": version: 2.0.1 resolution: "parse-conflict-json@npm:2.0.1" @@ -31093,13 +30910,6 @@ __metadata: languageName: node linkType: hard -"parse-headers@npm:^2.0.0": - version: 2.0.4 - resolution: "parse-headers@npm:2.0.4" - checksum: 29519ac013e100c11a67d0fc64eb33ae86523abf547f71dba36d484dcd16a2835dd11f31303f4ded27c40133dca5a5fe4d15b77f49091e470a6f74a023c59c4a - languageName: node - linkType: hard - "parse-json@npm:^2.2.0": version: 2.2.0 resolution: "parse-json@npm:2.2.0" @@ -31109,16 +30919,6 @@ __metadata: languageName: node linkType: hard -"parse-json@npm:^4.0.0": - version: 4.0.0 - resolution: "parse-json@npm:4.0.0" - dependencies: - error-ex: ^1.3.1 - json-parse-better-errors: ^1.0.1 - checksum: 0fe227d410a61090c247e34fa210552b834613c006c2c64d9a05cfe9e89cf8b4246d1246b1a99524b53b313e9ac024438d0680f67e33eaed7e6f38db64cfe7b5 - languageName: node - linkType: hard - "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -31131,13 +30931,6 @@ __metadata: languageName: node linkType: hard -"parse-package-name@npm:^0.1.0": - version: 0.1.0 - resolution: "parse-package-name@npm:0.1.0" - checksum: 7d69b1deeaf82d5a59536c5a8772c8db003b1415dd2465073343dfab5caf90917ecfffdd71d1c004f5cf963c3881ccb8899d0ff820eac705a272e817e246de14 - languageName: node - linkType: hard - "parse-path@npm:^7.0.0": version: 7.0.0 resolution: "parse-path@npm:7.0.0" @@ -31172,20 +30965,6 @@ __metadata: languageName: node linkType: hard -"parseqs@npm:0.0.6": - version: 0.0.6 - resolution: "parseqs@npm:0.0.6" - checksum: 7fc4ff4ba59764060bb8529875f6d4313056ea6939ff579b22dd7bd6f6033035e1fd2d6a559ab48ef0a7fa29a9d7731c982bfd1594e9115141fe1c328485ce9e - languageName: node - linkType: hard - -"parseuri@npm:0.0.6": - version: 0.0.6 - resolution: "parseuri@npm:0.0.6" - checksum: fa430e40f0c75293a28e5f1023da5f51a5038d5e34c48c517b0d5187143f6bcc67d3091a062b68765db4a22757e488c7d15854f9d1921f2c2b9afa5ca0629a84 - languageName: node - linkType: hard - "parseurl@npm:^1.3.3, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -31424,7 +31203,7 @@ __metadata: languageName: node linkType: hard -"path-is-inside@npm:1.0.2, path-is-inside@npm:^1.0.2": +"path-is-inside@npm:1.0.2": version: 1.0.2 resolution: "path-is-inside@npm:1.0.2" checksum: 0b5b6c92d3018b82afb1f74fe6de6338c4c654de4a96123cb343f2b747d5606590ac0c890f956ed38220a4ab59baddfd7b713d78a62d240b20b14ab801fa02cb @@ -31523,15 +31302,6 @@ __metadata: languageName: node linkType: hard -"path-type@npm:^3.0.0": - version: 3.0.0 - resolution: "path-type@npm:3.0.0" - dependencies: - pify: ^3.0.0 - checksum: 735b35e256bad181f38fa021033b1c33cfbe62ead42bb2222b56c210e42938eecb272ae1949f3b6db4ac39597a61b44edd8384623ec4d79bfdc9a9c0f12537a6 - languageName: node - linkType: hard - "path-type@npm:^4.0.0": version: 4.0.0 resolution: "path-type@npm:4.0.0" @@ -31676,10 +31446,10 @@ __metadata: languageName: node linkType: hard -"phin@npm:^2.9.1": - version: 2.9.3 - resolution: "phin@npm:2.9.3" - checksum: 7e2abd7be74a54eb7be92dccb1d7a019725c8adaa79ac22a38f25220f9a859393e654ea753a559d326aed7bbc966fadac88270cc8c39d78896f7784219560c47 +"photoswipe@npm:^5.3.5": + version: 5.3.5 + resolution: "photoswipe@npm:5.3.5" + checksum: bd3eafebffc114210b8e5403746b48a9bfe436cca05a65f8d5efd6eacea785a51f0f124d7326c8f651d754d76124c9768a920383843c4a619da582a86e535b27 languageName: node linkType: hard @@ -31713,13 +31483,6 @@ __metadata: languageName: node linkType: hard -"pify@npm:^3.0.0": - version: 3.0.0 - resolution: "pify@npm:3.0.0" - checksum: 6cdcbc3567d5c412450c53261a3f10991665d660961e06605decf4544a61a97a54fefe70a68d5c37080ff9d6f4cf51444c90198d1ba9f9309a6c0d6e9f5c4fde - languageName: node - linkType: hard - "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -31799,14 +31562,14 @@ __metadata: languageName: node linkType: hard -"pixelmatch@npm:^4.0.2": - version: 4.0.2 - resolution: "pixelmatch@npm:4.0.2" +"pixelmatch@npm:5.3.0": + version: 5.3.0 + resolution: "pixelmatch@npm:5.3.0" dependencies: - pngjs: ^3.0.0 + pngjs: ^6.0.0 bin: pixelmatch: bin/pixelmatch - checksum: 9c5c1329001938cae6d01e2bb84a909ba767f8256bcafc075422cea2a4dbaa8bebd44fceaa4b4ce7cdc36d11f20d4f1ba0cf669851d5649b32d8d1d27e4f5a36 + checksum: f542713d89536551181ad9ddb666a1792ba00a8632d831093232a075cb3ccac05856e7a453ed7d0a41aaef64dcb5962e8ae5cbe646dd2761790d8ee51b0a0743 languageName: node linkType: hard @@ -31858,10 +31621,10 @@ __metadata: languageName: node linkType: hard -"pngjs@npm:^3.0.0, pngjs@npm:^3.3.3": - version: 3.4.0 - resolution: "pngjs@npm:3.4.0" - checksum: 8bd40bd698abd16b72c97b85cb858c80894fbedc76277ce72a784aa441e14795d45d9856e97333ca469b34b67528860ffc8a7317ca6beea349b645366df00bcd +"pngjs@npm:6.0.0, pngjs@npm:^6.0.0": + version: 6.0.0 + resolution: "pngjs@npm:6.0.0" + checksum: ab6c285086060087097eab9fe6b5a528a24f9e79c03dea2b4fd6264ed4fdb5beff4a3257eeeaf2a9dc18249b539609c2a4e4013c567164a1f6b5ba2c974d5ecb languageName: node linkType: hard @@ -31872,6 +31635,13 @@ __metadata: languageName: node linkType: hard +"popper.js@npm:^1.14.1": + version: 1.16.1 + resolution: "popper.js@npm:1.16.1" + checksum: c56ae5001ec50a77ee297a8061a0221d99d25c7348d2e6bcd3e45a0d0f32a1fd81bca29d46cb0d4bdf13efb77685bd6a0ce93f9eb3c608311a461f945fffedbe + languageName: node + linkType: hard + "postcss-calc@npm:^8.0.0": version: 8.0.0 resolution: "postcss-calc@npm:8.0.0" @@ -32321,9 +32091,9 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.1.0": - version: 7.1.0 - resolution: "prebuild-install@npm:7.1.0" +"prebuild-install@npm:^7.1.0, prebuild-install@npm:^7.1.1": + version: 7.1.1 + resolution: "prebuild-install@npm:7.1.1" dependencies: detect-libc: ^2.0.0 expand-template: ^2.0.3 @@ -32332,7 +32102,6 @@ __metadata: mkdirp-classic: ^0.5.3 napi-build-utils: ^1.0.1 node-abi: ^3.3.0 - npmlog: ^4.0.1 pump: ^3.0.0 rc: ^1.2.7 simple-get: ^4.0.0 @@ -32340,7 +32109,7 @@ __metadata: tunnel-agent: ^0.6.0 bin: prebuild-install: bin.js - checksum: 204f2d89c6d6179fa1039036514aa72f7d0b537e421ef72c40840286e318f41489f00f22c6acc725cce6e10d43825b69dcabeaadfc917db781c58cd56fc25f90 + checksum: dbf96d0146b6b5827fc8f67f72074d2e19c69628b9a7a0a17d0fad1bf37e9f06922896972e074197fc00a52eae912993e6ef5a0d471652f561df5cb516f3f467 languageName: node linkType: hard @@ -32377,21 +32146,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^1.16.4": - version: 1.19.1 - resolution: "prettier@npm:1.19.1" - bin: - prettier: ./bin-prettier.js - checksum: bc78219e0f8173a808f4c6c8e0a137dd8ebd4fbe013e63fe1a37a82b48612f17b8ae8e18a992adf802ee2cf7428f14f084e7c2846ca5759cf4013c6e54810e1f - languageName: node - linkType: hard - "prettier@npm:^2.2.1, prettier@npm:^2.7.1": - version: 2.8.1 - resolution: "prettier@npm:2.8.1" + version: 2.8.4 + resolution: "prettier@npm:2.8.4" bin: prettier: bin-prettier.js - checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc + checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e languageName: node linkType: hard @@ -32556,7 +32316,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.0.0, prop-types@npm:^15.5.10, prop-types@npm:^15.5.7, prop-types@npm:^15.5.8, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.0.0, prop-types@npm:^15.5.10, prop-types@npm:^15.5.7, prop-types@npm:^15.5.8, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -33134,6 +32894,19 @@ __metadata: languageName: node linkType: hard +"react-event-listener@npm:^0.6.2": + version: 0.6.6 + resolution: "react-event-listener@npm:0.6.6" + dependencies: + "@babel/runtime": ^7.2.0 + prop-types: ^15.6.0 + warning: ^4.0.1 + peerDependencies: + react: ^16.3.0 + checksum: 0287e0ae8cbf0a4c03889ffc2b745f5494b3edea0f4667357d709f5646dd78c7289ce305b6f473ec6ac5789f8a937c86b7e543d0249f0bf787bccdb1eab7ecd0 + languageName: node + linkType: hard + "react-fast-compare@npm:^3.1.1": version: 3.2.0 resolution: "react-fast-compare@npm:3.2.0" @@ -33174,15 +32947,6 @@ __metadata: languageName: node linkType: hard -"react-icons@npm:^4.4.0": - version: 4.4.0 - resolution: "react-icons@npm:4.4.0" - peerDependencies: - react: "*" - checksum: dd93a1dcc8ac8a3cf46a2b33e80b586fa967331fa5fcb90d061abf276155a8363a331643e203d67cb9bab4261d00a757da854bcce1fce2c6e4258bf3e33f711b - languageName: node - linkType: hard - "react-immutable-proptypes@npm:2.2.0": version: 2.2.0 resolution: "react-immutable-proptypes@npm:2.2.0" @@ -33214,7 +32978,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -33235,7 +32999,7 @@ __metadata: languageName: node linkType: hard -"react-lifecycles-compat@npm:^3.0.4": +"react-lifecycles-compat@npm:^3.0.2, react-lifecycles-compat@npm:^3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f @@ -33436,7 +33200,7 @@ __metadata: languageName: node linkType: hard -"react-transition-group@npm:2.9.0": +"react-transition-group@npm:2.9.0, react-transition-group@npm:^2.2.1": version: 2.9.0 resolution: "react-transition-group@npm:2.9.0" dependencies: @@ -33748,6 +33512,22 @@ __metadata: languageName: node linkType: hard +"recompose@npm:0.28.0 - 0.30.0": + version: 0.30.0 + resolution: "recompose@npm:0.30.0" + dependencies: + "@babel/runtime": ^7.0.0 + change-emitter: ^0.1.2 + fbjs: ^0.8.1 + hoist-non-react-statics: ^2.3.1 + react-lifecycles-compat: ^3.0.2 + symbol-observable: ^1.0.4 + peerDependencies: + react: ^0.14.0 || ^15.0.0 || ^16.0.0 + checksum: 18e58252336d0628b22db1e38407d32e836648e6d5c9453ba37c9f8030138b3429ee3952b053a13b60311f8b60893b207a761466bb293083542db0cf317b7a41 + languageName: node + linkType: hard + "recursive-readdir@npm:^2.2.2": version: 2.2.3 resolution: "recursive-readdir@npm:2.2.3" @@ -33859,7 +33639,7 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.3, regenerator-runtime@npm:^0.13.4": +"regenerator-runtime@npm:^0.13.11, regenerator-runtime@npm:^0.13.4": version: 0.13.11 resolution: "regenerator-runtime@npm:0.13.11" checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 @@ -34190,7 +33970,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.0, resolve@npm:~1.22.1": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:~1.22.1": version: 1.22.1 resolution: "resolve@npm:1.22.1" dependencies: @@ -34235,7 +34015,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.0#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.1 resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin::version=1.22.1&hash=07638b" dependencies: @@ -34697,15 +34477,6 @@ __metadata: languageName: node linkType: hard -"sanitize-filename@npm:^1.6.1": - version: 1.6.3 - resolution: "sanitize-filename@npm:1.6.3" - dependencies: - truncate-utf8-bytes: ^1.0.0 - checksum: aa733c012b7823cf65730603cf3b503c641cee6b239771d3164ca482f22d81a50e434a713938d994071db18e4202625669cc56bccc9d13d818b4c983b5f47fde - languageName: node - linkType: hard - "sax@npm:1.2.1": version: 1.2.1 resolution: "sax@npm:1.2.1" @@ -34827,6 +34598,13 @@ __metadata: languageName: node linkType: hard +"select@npm:^1.1.2": + version: 1.1.2 + resolution: "select@npm:1.1.2" + checksum: 4346151e94f226ea6131e44e68e6d837f3fdee64831b756dd657cc0b02f4cb5107f867cb34a1d1216ab7737d0bf0645d44546afb030bbd8d64e891f5e4c4814e + languageName: node + linkType: hard + "selfsigned@npm:^2.0.0, selfsigned@npm:^2.1.1": version: 2.1.1 resolution: "selfsigned@npm:2.1.1" @@ -35077,6 +34855,23 @@ __metadata: languageName: node linkType: hard +"sharp@npm:0.31.2": + version: 0.31.2 + resolution: "sharp@npm:0.31.2" + dependencies: + color: ^4.2.3 + detect-libc: ^2.0.1 + node-addon-api: ^5.0.0 + node-gyp: latest + prebuild-install: ^7.1.1 + semver: ^7.3.8 + simple-get: ^4.0.1 + tar-fs: ^2.1.1 + tunnel-agent: ^0.6.0 + checksum: 076717b7a073ea47bb522ff2931b74b6608daeb6f7ae334e4848d47fdf4d23bcb18cd49044fd5fb27ef27a1a4aa87d141894d67d1c4bb15a6e2e63cf4dbe329e + languageName: node + linkType: hard + "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -35234,13 +35029,6 @@ __metadata: languageName: node linkType: hard -"slash@npm:^1.0.0": - version: 1.0.0 - resolution: "slash@npm:1.0.0" - checksum: 4b6e21b1fba6184a7e2efb1dd173f692d8a845584c1bbf9dc818ff86f5a52fc91b413008223d17cc684604ee8bb9263a420b1182027ad9762e35388434918860 - languageName: node - linkType: hard - "slash@npm:^2.0.0": version: 2.0.0 resolution: "slash@npm:2.0.0" @@ -35320,68 +35108,6 @@ __metadata: languageName: node linkType: hard -"socket.io-adapter@npm:~1.1.0": - version: 1.1.2 - resolution: "socket.io-adapter@npm:1.1.2" - checksum: 8e18df7f8c471001b65e43542c5c743b63f041781bca097b4a407dd199dd757c14c0d470992f84923f48e75729a2ac0ae634fec820f20881cadae8a495bf68e9 - languageName: node - linkType: hard - -"socket.io-client@npm:2.5.0, socket.io-client@npm:^2.2.0": - version: 2.5.0 - resolution: "socket.io-client@npm:2.5.0" - dependencies: - backo2: 1.0.2 - component-bind: 1.0.0 - component-emitter: ~1.3.0 - debug: ~3.1.0 - engine.io-client: ~3.5.0 - has-binary2: ~1.0.2 - indexof: 0.0.1 - parseqs: 0.0.6 - parseuri: 0.0.6 - socket.io-parser: ~3.3.0 - to-array: 0.1.4 - checksum: a33accaf02c4a4c47ac9b09018fa4b9fa67a648a0cc92602e520ec884520050796786eb0df78fc1a9bf51e7b3d7b50ba4ffd3bda6e44df2c253a77100124669c - languageName: node - linkType: hard - -"socket.io-parser@npm:~3.3.0": - version: 3.3.3 - resolution: "socket.io-parser@npm:3.3.3" - dependencies: - component-emitter: ~1.3.0 - debug: ~3.1.0 - isarray: 2.0.1 - checksum: 6cf464e324e4207811dbf994822c0aa18ba01d615fbed8e3f069927e0e402fdc9b3ac3d2657f18d481fb8c584b1fd40152ced15b3686982a51ec843c6a76dbc2 - languageName: node - linkType: hard - -"socket.io-parser@npm:~3.4.0": - version: 3.4.1 - resolution: "socket.io-parser@npm:3.4.1" - dependencies: - component-emitter: 1.2.1 - debug: ~4.1.0 - isarray: 2.0.1 - checksum: f8bac61298375680aceb6c72ffbb47a2d950daa05e01a3b67d9330945073ae01e35aa131dcddd7e0b354ca302c51742bebaae57a50c188d4c1fe8af9461aa38d - languageName: node - linkType: hard - -"socket.io@npm:^2.2.0": - version: 2.5.0 - resolution: "socket.io@npm:2.5.0" - dependencies: - debug: ~4.1.0 - engine.io: ~3.6.0 - has-binary2: ~1.0.2 - socket.io-adapter: ~1.1.0 - socket.io-client: 2.5.0 - socket.io-parser: ~3.4.0 - checksum: 6f20a413352cb0a8bb13063249fe425c81fb54beca1bdd71221262305cf21232e6a37fdd4a232b5695dbd4d3204281a9313829c9c373c5ba01c5bd7218edd094 - languageName: node - linkType: hard - "sockjs@npm:^0.3.24": version: 0.3.24 resolution: "sockjs@npm:0.3.24" @@ -35459,7 +35185,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.10, source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.21, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -36018,6 +35744,13 @@ __metadata: languageName: node linkType: hard +"string.prototype.repeat@npm:^0.2.0": + version: 0.2.0 + resolution: "string.prototype.repeat@npm:0.2.0" + checksum: 5127ce1b5bce45258905877048ac28bae71be18f1c3421011bd3979cfbcacf9c16f6b7f42daa3b999c9d90f5da39bd7136982c8e64439f02666dd6c0778ed262 + languageName: node + linkType: hard + "string.prototype.trimend@npm:^1.0.5": version: 1.0.5 resolution: "string.prototype.trimend@npm:1.0.5" @@ -36365,6 +36098,13 @@ __metadata: languageName: node linkType: hard +"svg-pan-zoom@npm:^3.6.0": + version: 3.6.1 + resolution: "svg-pan-zoom@npm:3.6.1" + checksum: 500b99378d321315e1668067ef6a73af3f61f9adfab75a575b21d2d216cb446def61d60ad12265203463cca9bef56b090f00e48118fa9b7f0ffa1c691e4c1621 + languageName: node + linkType: hard + "svg-parser@npm:^2.0.4": version: 2.0.4 resolution: "svg-parser@npm:2.0.4" @@ -36485,7 +36225,7 @@ __metadata: languageName: node linkType: hard -"symbol-observable@npm:1.2.0, symbol-observable@npm:^1.0.4": +"symbol-observable@npm:1.2.0, symbol-observable@npm:^1.0.4, symbol-observable@npm:^1.1.0": version: 1.2.0 resolution: "symbol-observable@npm:1.2.0" checksum: 48ffbc22e3d75f9853b3ff2ae94a44d84f386415110aea5effc24d84c502e03a4a6b7a8f75ebaf7b585780bda34eb5d6da3121f826a6f93398429d30032971b6 @@ -36610,7 +36350,7 @@ __metadata: "@backstage/plugin-techdocs-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@material-ui/core": ^4.11.0 + "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 @@ -36824,13 +36564,6 @@ __metadata: languageName: node linkType: hard -"timm@npm:^1.6.1": - version: 1.7.1 - resolution: "timm@npm:1.7.1" - checksum: c80df538ec7fae50a0e3183931b20fbe97f6f2c06907d9675eb7b9d90b3f788af7742285c730192db3b066c4ab22ebae75f8d21970c5b03f38d928d5bb2a0339 - languageName: node - linkType: hard - "timsort@npm:^0.3.0": version: 0.3.0 resolution: "timsort@npm:0.3.0" @@ -36838,6 +36571,13 @@ __metadata: languageName: node linkType: hard +"tiny-emitter@npm:^2.0.0": + version: 2.1.0 + resolution: "tiny-emitter@npm:2.1.0" + checksum: fbcfb5145751a0e3b109507a828eb6d6d4501352ab7bb33eccef46e22e9d9ad3953158870a6966a59e57ab7c3f9cfac7cab8521db4de6a5e757012f4677df2dd + languageName: node + linkType: hard + "tiny-invariant@npm:^1.0.6": version: 1.1.0 resolution: "tiny-invariant@npm:1.1.0" @@ -36859,13 +36599,6 @@ __metadata: languageName: node linkType: hard -"tinycolor2@npm:^1.4.1": - version: 1.4.2 - resolution: "tinycolor2@npm:1.4.2" - checksum: 57ed262e08815a4ab0ed933edafdbc6555a17081781766149813b44a080ecbe58b3ee281e81c0e75b42e4d41679f138cfa98eabf043f829e0683c04adb12c031 - languageName: node - linkType: hard - "title-case@npm:^3.0.3": version: 3.0.3 resolution: "title-case@npm:3.0.3" @@ -36909,13 +36642,6 @@ __metadata: languageName: node linkType: hard -"to-array@npm:0.1.4": - version: 0.1.4 - resolution: "to-array@npm:0.1.4" - checksum: 396a04df5a5e74df5c8891ebb819d575d626e2929312fec3d649b4d38203bbf7185c270cb31fcad903564743895e935f2e965770bd1c6eb137dde48c4d60788d - languageName: node - linkType: hard - "to-arraybuffer@npm:^1.0.0": version: 1.0.1 resolution: "to-arraybuffer@npm:1.0.1" @@ -37089,15 +36815,6 @@ __metadata: languageName: node linkType: hard -"truncate-utf8-bytes@npm:^1.0.0": - version: 1.0.2 - resolution: "truncate-utf8-bytes@npm:1.0.2" - dependencies: - utf8-byte-length: ^1.0.1 - checksum: ad097314709ea98444ad9c80c03aac8da805b894f37ceb5685c49ad297483afe3a5ec9572ebcaff699dda72b6cd447a2ba2a3fd10e96c2628cd16d94abeb328a - languageName: node - linkType: hard - "tryer@npm:^1.0.1": version: 1.0.1 resolution: "tryer@npm:1.0.1" @@ -37432,7 +37149,7 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^0.7.18": +"ua-parser-js@npm:^0.7.18, ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" checksum: 1510e9ec26fcaf0d8c6ae8f1078a8230e8816f083e1b5f453ea19d06b8ef2b8a596601c92148fd41899e8b3e5f83fa69c42332bd5729b931a721040339831696 @@ -37561,15 +37278,6 @@ __metadata: languageName: node linkType: hard -"unidiff@npm:1.0.2": - version: 1.0.2 - resolution: "unidiff@npm:1.0.2" - dependencies: - diff: ^2.2.2 - checksum: 442d699d44a07f7511e2ec5b6433fb562d6ddce9eb91c6c28ff23bdda60595d9d7e8c6341937f18996ca03c198d93cc9b8fb448dde211ddeeb45bb45bff8ca1e - languageName: node - linkType: hard - "unified@npm:^10.0.0": version: 10.1.0 resolution: "unified@npm:10.1.0" @@ -37877,22 +37585,6 @@ __metadata: languageName: node linkType: hard -"utf8-byte-length@npm:^1.0.1": - version: 1.0.4 - resolution: "utf8-byte-length@npm:1.0.4" - checksum: f188ca076ec094d58e7009fcc32623c5830c7f0f3e15802bfa4fdd1e759454a481fc4ac05e0fa83b7736e77af628a9ee0e57dcc89683d688fde3811473e42143 - languageName: node - linkType: hard - -"utif@npm:^2.0.1": - version: 2.0.1 - resolution: "utif@npm:2.0.1" - dependencies: - pako: ^1.0.5 - checksum: 66b0bffc18f08834a34c44846f189b2223418e8bddfff3882e07fccea54436737f7334e27c86cbff46e247487dc92377b7a17428a7aafc5d5c733d61bed39038 - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -38176,6 +37868,13 @@ __metadata: languageName: node linkType: hard +"viz.js@npm:2.1.2": + version: 2.1.2 + resolution: "viz.js@npm:2.1.2" + checksum: 299e5a8519a472e0e98197c5f39c0ca6f3f6c4642b6ae007ed888fea998d82455c7ae0118d09cb888bfd2c46ebe3b03d7ce321a4eef1c822a5f5719d3a6ef3bb + languageName: node + linkType: hard + "vm-browserify@npm:^1.0.1": version: 1.1.2 resolution: "vm-browserify@npm:1.1.2" @@ -38184,14 +37883,14 @@ __metadata: linkType: hard "vm2@npm:^3.9.11": - version: 3.9.13 - resolution: "vm2@npm:3.9.13" + version: 3.9.14 + resolution: "vm2@npm:3.9.14" dependencies: acorn: ^8.7.0 acorn-walk: ^8.2.0 bin: vm2: bin/vm2 - checksum: ee82c130a9d1b45558fac4e95133ae022e69fafd4bec8aada44bb2f0aebe6ff8ae9b1176e7cbafceffec35267e009b518c121ad81a5565da06aa7a50ed3a09bc + checksum: 1ed7481e07ce8e03055101b382bfbf0d725a5c9b9bbe8bf75f71501cb43a6bd22f6a0a151975ff7cea8cad136d47e66d64f0a3248913f6d3ca3c405db12bacc0 languageName: node linkType: hard @@ -38274,6 +37973,24 @@ __metadata: languageName: node linkType: hard +"warning@npm:^3.0.0": + version: 3.0.0 + resolution: "warning@npm:3.0.0" + dependencies: + loose-envify: ^1.0.0 + checksum: c9f99a12803aab81b29858e7dc3415bf98b41baee3a4c3acdeb680d98c47b6e17490f1087dccc54432deed5711a5ce0ebcda2b27e9b5eb054c32ae50acb4419c + languageName: node + linkType: hard + +"warning@npm:^4.0.1": + version: 4.0.3 + resolution: "warning@npm:4.0.3" + dependencies: + loose-envify: ^1.0.0 + checksum: 4f2cb6a9575e4faf71ddad9ad1ae7a00d0a75d24521c193fa464f30e6b04027bd97aa5d9546b0e13d3a150ab402eda216d59c1d0f2d6ca60124d96cd40dfa35c + languageName: node + linkType: hard + "watchpack@npm:^2.0.0-beta.10, watchpack@npm:^2.4.0": version: 2.4.0 resolution: "watchpack@npm:2.4.0" @@ -38526,7 +38243,7 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:^3.0.0, whatwg-fetch@npm:^3.4.1": +"whatwg-fetch@npm:>=0.10.0, whatwg-fetch@npm:^3.4.1": version: 3.6.2 resolution: "whatwg-fetch@npm:3.6.2" checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed @@ -38845,21 +38562,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:~7.4.2": - version: 7.4.6 - resolution: "ws@npm:7.4.6" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 3a990b32ed08c72070d5e8913e14dfcd831919205be52a3ff0b4cdd998c8d554f167c9df3841605cde8b11d607768cacab3e823c58c96a5c08c987e093eb767a - languageName: node - linkType: hard - "xcase@npm:^2.0.1": version: 2.0.1 resolution: "xcase@npm:2.0.1" @@ -38867,18 +38569,6 @@ __metadata: languageName: node linkType: hard -"xhr@npm:^2.0.1": - version: 2.6.0 - resolution: "xhr@npm:2.6.0" - dependencies: - global: ~4.4.0 - is-function: ^1.0.1 - parse-headers: ^2.0.0 - xtend: ^4.0.0 - checksum: a1db277e37737caf3ed363d2a33ce4b4ea5b5fc190b663a6f70bc252799185b840ccaa166eaeeea4841c9c60b87741f0a24e29cbcf6708dd425986d4df186d2f - languageName: node - linkType: hard - "xml-but-prettier@npm:^1.0.1": version: 1.0.1 resolution: "xml-but-prettier@npm:1.0.1" @@ -38923,13 +38613,6 @@ __metadata: languageName: node linkType: hard -"xml-parse-from-string@npm:^1.0.0": - version: 1.0.1 - resolution: "xml-parse-from-string@npm:1.0.1" - checksum: 5155cb98e428409829f4060ce542c55438b2f7646d11fd306d850eaf12d35c06ffd9e86d76aa5230121a533b958fd1a319d6f90a5c113391853d0ff01f4da7bb - languageName: node - linkType: hard - "xml2js@npm:0.4.19": version: 0.4.19 resolution: "xml2js@npm:0.4.19" @@ -38940,7 +38623,7 @@ __metadata: languageName: node linkType: hard -"xml2js@npm:^0.4.11, xml2js@npm:^0.4.19, xml2js@npm:^0.4.23, xml2js@npm:^0.4.5": +"xml2js@npm:^0.4.11, xml2js@npm:^0.4.19, xml2js@npm:^0.4.23": version: 0.4.23 resolution: "xml2js@npm:0.4.23" dependencies: @@ -38992,13 +38675,6 @@ __metadata: languageName: node linkType: hard -"xmlhttprequest-ssl@npm:~1.6.2": - version: 1.6.3 - resolution: "xmlhttprequest-ssl@npm:1.6.3" - checksum: ac8e5de1cdd170bddb928de75393e8977e7eb80c0d8c24fe4be07f6aa1d5c8e2e42296d29abca6591ec2046cc708c220791ecfa56db43c958b8e4de8e7d39984 - languageName: node - linkType: hard - "xpath@npm:0.0.32": version: 0.0.32 resolution: "xpath@npm:0.0.32" @@ -39203,13 +38879,6 @@ __metadata: languageName: node linkType: hard -"yeast@npm:0.1.2": - version: 0.1.2 - resolution: "yeast@npm:0.1.2" - checksum: 81a250b69f601fed541e9518eb2972e75631dd81231689503d7f288612d4eec793b29c208d6807fd6bfc4c2a43614d0c6db233739a4ae6223e244aaed6a885c0 - languageName: node - linkType: hard - "yeoman-environment@npm:^3.9.1": version: 3.13.0 resolution: "yeoman-environment@npm:3.13.0"