Merge branch 'backstage:master' into Track-the-last-time-the-final-entity-changed

This commit is contained in:
iriswang233
2022-12-12 11:52:37 +08:00
committed by GitHub
481 changed files with 10093 additions and 1856 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': minor
---
Fixes in kind selectors (now `OwnershipCard` works again). `EntityKindPicker` now accepts an optional `allowedKinds` prop, just like `CatalogKindHeader`.
+20
View File
@@ -0,0 +1,20 @@
---
'@backstage/core-plugin-api': minor
---
Added a new `display` property to the `AlertMessage` which can accept the values `permanent` or `transient`.
Here's a rough example of how to trigger an alert using the new `display` property:
```ts
import { alertApiRef, useApi } from '@backstage/core-plugin-api';
const ExampleTransient = () => {
const alertApi = useApi(alertApiRef);
alertApi.post({
message: 'Example of Transient Alert',
severity: 'success',
display: 'transient',
});
};
```
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Fix dependency ordering in templated packages.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Bumped create-app version.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
added default project name for CI job compatibility
+9
View File
@@ -0,0 +1,9 @@
---
'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch
'@backstage/plugin-scaffolder-backend-module-rails': patch
'@backstage/plugin-scaffolder-backend-module-yeoman': patch
'@backstage/create-app': patch
'@backstage/plugin-scaffolder-backend': patch
---
Change step output template examples to use square bracket syntax.
+10
View File
@@ -0,0 +1,10 @@
---
'@backstage/plugin-bazaar-backend': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
'@backstage/plugin-playlist-backend': patch
'@backstage/plugin-search-backend-module-pg': patch
'@backstage/plugin-user-settings-backend': patch
---
Ensured typescript type checks in migration files.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Removed the unused dependency on `@sucrase/jest-plugin`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Fixed GitlabUrlReader to include api tokens in API calls
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Updated Jest coverage configuration to only apply either in the root project or package configuration, depending on whether repo or package tests are run.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Fix webpack dev server issue where it wasn't serving `index.html` from correct endpoint on subsequent requests.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
Fix for the automatic rewriting of base URLs.
+21
View File
@@ -0,0 +1,21 @@
---
'@backstage/plugin-scaffolder-backend': minor
---
Deprecated the `taskWorkers` option in RouterOptions in favor of `concurrentTasksLimit` which sets the limit of concurrent tasks in a single TaskWorker
TaskWorker can now run multiple (defaults to 10) tasks concurrently using the `concurrentTasksLimit` option available in both `RouterOptions` and `CreateWorkerOptions`.
To use the option to create a TaskWorker:
```diff
const worker = await TaskWorker.create({
taskBroker,
actionRegistry,
integrations,
logger,
workingDirectory,
additionalTemplateFilters,
+ concurrentTasksLimit: 10 // (1 to Infinity)
});
```
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/cli': minor
---
The Jest configuration that was previously enabled with `BACKSTAGE_NEXT_TESTS` is now enabled by default. To revert to the old configuration you can now instead set `BACKSTAGE_OLD_TESTS`.
This new configuration uses the `babel` coverage provider rather than `v8`. It used to be that `v8` worked better when using Sucrase for transpilation, but now that we have switched to SWC, `babel` seems to work better. In addition, the new configuration also enables source maps by default, as they no longer have a negative impact on code coverage accuracy, and it also enables a modified Jest runtime with additional caching of script objects.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-react': patch
---
Cleanup and small fixes for the kind selector
+1 -1
View File
@@ -2,4 +2,4 @@
'@backstage/plugin-jenkins-backend': patch
---
Remove unnecessary dependency promise-any-polyfill
Remove unnecessary dependency `promise-any-polyfill`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
Prevent duplicate feature flag components from rendering in the settings when using <FeatureFlagged /> components
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-cost-insights': patch
---
Internal refactor to avoid usage of deprecated symbols
+51
View File
@@ -195,81 +195,132 @@
"changesets": [
"angry-dingos-lick",
"angry-trees-relax",
"beige-chairs-repair",
"blue-chefs-know",
"brave-bags-sniff",
"chilled-ladybugs-cough",
"chilly-ads-lay",
"chilly-tables-crash",
"clean-paws-fry",
"clean-seals-whisper",
"clever-pillows-drive",
"clever-rivers-obey",
"create-app-1669131574",
"create-app-1669720399",
"create-app-1670332900",
"cyan-donkeys-arrive",
"dry-melons-listen",
"dry-radios-live",
"early-hairs-switch",
"early-parrots-guess",
"eight-eels-compete",
"eight-spiders-know",
"eight-tables-hunt",
"eleven-jeans-train",
"empty-taxis-run",
"fair-walls-talk",
"famous-cobras-suffer",
"famous-crews-speak",
"fast-lies-remain",
"fifty-news-stare",
"five-trainers-admire",
"fluffy-walls-approve",
"forty-baboons-burn",
"four-adults-provide",
"four-buttons-clean",
"fresh-news-push",
"funny-numbers-compete",
"gentle-ligers-help",
"gold-icons-cheat",
"gold-yaks-join",
"gorgeous-hairs-applaud",
"green-deers-turn",
"healthy-crabs-collect",
"hip-chairs-tap",
"hip-stingrays-kneel",
"hip-wasps-yell",
"itchy-walls-boil",
"kind-walls-share",
"light-snakes-exercise",
"light-turtles-yawn",
"little-chairs-dance",
"loud-rockets-reply",
"loud-snails-sleep",
"many-bikes-press",
"modern-camels-cheat",
"modern-jokes-attack",
"modern-mugs-shout",
"nasty-melons-build",
"neat-lies-know",
"nervous-mice-flow",
"new-bugs-march",
"nice-apricots-love",
"nice-pants-boil",
"nine-ears-whisper",
"old-bulldogs-fry",
"old-keys-leave",
"old-sloths-warn",
"old-tips-cough",
"pretty-eagles-matter",
"pretty-melons-taste",
"quick-horses-cry",
"renovate-1e2853d",
"renovate-3fe8460",
"renovate-4bb70f3",
"renovate-4cbe4f9",
"renovate-50ee0c3",
"renovate-61ad428",
"renovate-778b2fa",
"renovate-8c69aed",
"renovate-a5f7839",
"renovate-bf8dfb3",
"renovate-ceb9248",
"renovate-ebb2ea1",
"rich-balloons-leave",
"rich-garlics-play",
"rude-pugs-deny",
"rude-sloths-cross",
"search-heavy-frogs-confess",
"search-lieutenant-dangle",
"search-om-manniskan-ginge",
"search-tofu-panaeng",
"selfish-lizards-invent",
"serious-windows-occur",
"sharp-shoes-bathe",
"short-turtles-dream",
"shy-cycles-add",
"silly-wolves-remember",
"silver-rats-rest",
"slow-dragons-promise",
"slow-eggs-grab",
"slow-flies-marinate",
"slow-flies-marry",
"slow-lies-jam",
"smart-radios-change",
"soft-nails-arrive",
"sour-flowers-care",
"sour-plums-grow",
"sour-queens-wait",
"spicy-pianos-train",
"strange-rocks-hide",
"strong-peaches-melt",
"strong-rice-warn",
"stupid-clocks-return",
"stupid-gifts-serve",
"sweet-pandas-relax",
"tender-colts-greet",
"tender-parrots-cover",
"thin-donuts-join",
"thin-flies-wink",
"twelve-meals-smell",
"twenty-dodos-wash",
"warm-parents-notice",
"weak-ears-jam",
"wicked-games-search",
"wicked-impalas-relate",
"wild-pears-enjoy",
"yellow-forks-knock",
"young-chairs-check",
"young-turkeys-relax"
]
}
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-common': patch
---
Updated dependency `@types/http-errors` to `^2.0.0`.
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/core-components': patch
'@backstage/plugin-gcp-projects': patch
'@backstage/plugin-scaffolder': patch
'@backstage/plugin-techdocs-module-addons-contrib': patch
---
Updated dependency `@react-hookz/web` to `^20.0.0`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
---
Make incremental providers more resilient to failures
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-airbrake': patch
---
Remove the `object-hash` dependency
+19
View File
@@ -0,0 +1,19 @@
---
'@backstage/core-components': patch
---
Added an option to allow the `AlertMessage` to be self-closing. This is done with a new `display` property that is set to `transient` on the `AlertMessage` when triggering a message to the `AlertApi`. The length of time that these transient messages stay open for can be set using the `transientTimeoutMs` prop on the `AlertDisplay` in the `App.tsx`. Here is an example:
```diff
const App = () => (
<AppProvider>
+ <AlertDisplay transientTimeoutMs={2500} />
<OAuthRequestDialog />
<AppRouter>
<Root>{routes}</Root>
</AppRouter>
</AppProvider>
);
```
The above example will set the transient timeout to 2500ms from the default of 5000ms
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
InfoCard - Remove subheader container when there is not a subheader or icon
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Bump `json-schema-library` to version `^7.3.9` which does not pull in the `gson-pointer` library
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Internal refactor to remove deprecated symbols.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
Made `WebStorage` notify its subscribers when `localStorage` values change in other tabs/windows
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': patch
---
Apps will now rewrite the `app.baseUrl` configuration to match the current `location.origin`. The `backend.baseUrl` will also be rewritten in the same way when the `app.baseUrl` and `backend.baseUrl` have matching origins. This will reduce the need for separate frontend builds for different environments.
+6 -4
View File
@@ -26,10 +26,12 @@ yarn.lock @backstage/reviewers @backst
/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-backend-module-aws @backstage/reviewers @pjungermann
/plugins/catalog-backend-module-bitbucket-cloud @backstage/reviewers @pjungermann
/plugins/catalog-backend-module-msgraph @backstage/reviewers @pjungermann
/plugins/catalog-graph @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
-2
View File
@@ -202,7 +202,6 @@ jobs:
if: ${{ steps.yarn-lock.outcome == 'success' }}
run: yarn backstage-cli repo test --maxWorkers=2 --workerIdleMemoryLimit=1300M --since origin/master
env:
BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }}
@@ -214,7 +213,6 @@ jobs:
yarn backstage-cli repo test --maxWorkers=2 --workerIdleMemoryLimit=800M --coverage
bash <(curl -s https://codecov.io/bash) -N $(git rev-parse FETCH_HEAD)
env:
BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }}
-1
View File
@@ -105,7 +105,6 @@ jobs:
bash <(curl -s https://codecov.io/bash) -f packages/core-components/coverage/* -F core-components
bash <(curl -s https://codecov.io/bash) -f packages/core-plugin-api/coverage/* -F core-plugin-api
env:
BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres13.ports[5432] }}
BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING: postgresql://postgres:postgres@localhost:${{ job.services.postgres9.ports[5432] }}
-1
View File
@@ -48,7 +48,6 @@ jobs:
- name: test
run: yarn backstage-cli repo test --maxWorkers=2 --workerIdleMemoryLimit=1300M
env:
BACKSTAGE_NEXT_TESTS: 1
BACKSTAGE_TEST_DISABLE_DOCKER: 1
# credit: https://github.com/appleboy/discord-action/issues/3#issuecomment-731426861
+1
View File
@@ -222,3 +222,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/
| [MSCI](http://msci.com) | [Stephen Burrows](mailto:stephen.burrows@msci.com) | Developer portal, service catalog, documentation and tooling
| [ESW](https://esw.com) | [Alisson Fabiano](https://github.com/afabianoo), [Bruno Quintella](https://github.com/quintelab) and [Guilherme Oenning](https://github.com/goenning) | Backstage is our one stop shop to find everything related to all our services, such as ownership, dependencies, production status, tech health and much more.
| [FanDuel](https://fanduel.com) | [Diego Herrera](https://github.com/diegoh), [Christy Campbell](https://github.com/FD-ChristopherCampbell) | We use backstage as our developer portal to provide visibility of our software, ownership, strategy, and the state of maturity across disciplines.
| [Affinidi](https://affinidi.com) | [Dmytro Shamenko](https://github.com/idestis), [Denis Fastovets](https://www.linkedin.com/in/denis-fastovets/) | The Backstage is used in the company to enhance development acceleration inside of the company and helps us keep the house in order, from cost efficiency and up to accountability.
+2 -2
View File
@@ -1,7 +1,7 @@
# Deploying Backstage on AWS using ECR and EKS
Backstage documentation shows how to build a [Docker
image](https://backstage.io/docs/getting-started/deployment-docker); this
image](https://backstage.io/docs/deployment/docker); this
tutorial shows how to deploy that Docker image to AWS using Elastic Container
Registry (ECR) and Elastic Kubernetes Service (EKS). Amazon also supports
deployments with Helm, covered in the [Helm
@@ -36,7 +36,7 @@ Go to [AWS IAM console](https://console.aws.amazon.com/iam/home) and select
## Publish a Backstage build
Follow the [Docker
image](https://backstage.io/docs/getting-started/deployment-docker)
image](https://backstage.io/docs/deployment/docker)
documentation to build a new Backstage Docker image:
```shell
+6 -6
View File
@@ -1415,22 +1415,22 @@ __metadata:
linkType: hard
"typescript@npm:^4.1.3":
version: 4.9.3
resolution: "typescript@npm:4.9.3"
version: 4.9.4
resolution: "typescript@npm:4.9.4"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 17b8f816050b412403e38d48eef0e893deb6be522d6dc7caf105e54a72e34daf6835c447735fd2b28b66784e72bfbf87f627abb4818a8e43d1fa8106396128dc
checksum: e782fb9e0031cb258a80000f6c13530288c6d63f1177ed43f770533fdc15740d271554cdae86701c1dd2c83b082cea808b07e97fd68b38a172a83dbf9e0d0ef9
languageName: node
linkType: hard
"typescript@patch:typescript@^4.1.3#~builtin<compat/typescript>":
version: 4.9.3
resolution: "typescript@patch:typescript@npm%3A4.9.3#~builtin<compat/typescript>::version=4.9.3&hash=a1c5e5"
version: 4.9.4
resolution: "typescript@patch:typescript@npm%3A4.9.4#~builtin<compat/typescript>::version=4.9.4&hash=a1c5e5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: ef65c22622d864497d0a0c5db693523329b3284c15fe632e93ad9aa059e8dc38ef3bd767d6f26b1e5ecf9446f49bd0f6c4e5714a2eeaf352805dc002479843d1
checksum: 37f6e2c3c5e2aa5934b85b0fddbf32eeac8b1bacf3a5b51d01946936d03f5377fe86255d4e5a4ae628fd0cd553386355ad362c57f13b4635064400f3e8e05b9d
languageName: node
linkType: hard
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

@@ -703,7 +703,7 @@ spec:
name: Register
action: catalog:register
input:
repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}'
repoContentsUrl: {{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
```
@@ -76,7 +76,7 @@ spec:
name: Register
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
```
@@ -169,14 +169,14 @@ These should be moved to `links` under the `output` object instead.
```diff
output:
- remoteUrl: '{{ steps.publish.output.remoteUrl }}'
- entityRef: '{{ steps.register.output.entityRef }}'
- remoteUrl: {{ steps['publish'].output.remoteUrl }}
- entityRef: {{ steps['register'].output.entityRef }}
+ links:
+ - title: Repository
+ url: ${{ steps.publish.output.remoteUrl }}
+ url: ${{ steps['publish'].output.remoteUrl }}
+ - title: Open in catalog
+ icon: catalog
+ entityRef: ${{ steps.register.output.entityRef }}
+ entityRef: ${{ steps['register'].output.entityRef }}
```
@@ -88,17 +88,17 @@ spec:
name: Register
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
# some outputs which are saved along with the job for use in the frontend
output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }}
url: ${{ steps['publish'].output.remoteUrl }}
- title: Open in catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }}
entityRef: ${{ steps['register'].output.entityRef }}
```
Let's dive in and pick apart what each of these sections do and what they are.
@@ -505,10 +505,10 @@ The main two that are used are the following:
output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }} # link to the remote repository
url: ${{ steps['publish'].output.remoteUrl }} # link to the remote repository
- title: Open in catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }} # link to the entity that has been ingested to the catalog
entityRef: ${{ steps['register'].output.entityRef }} # link to the entity that has been ingested to the catalog
```
## The templating syntax
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
---
title: Betterscan
author: Marcin Kozlowski
authorUrl: https://betterscan.io
category: Security
description: View security scanned vulnerabilities in Code and Cloud scanned using Open Source and proprietary scanners directly in Backstage.
documentation: https://github.com/marcinguy/betterscan-ce
iconUrl: https://uploads-ssl.webflow.com/6339e3b81867539b5fe2498d/633a1643dcb06d3029867161_g4.svg
npmPackageName: '@marcinguy/backstage-plugin-betterscan'
addedDate: '2022-12-08'
+12
View File
@@ -0,0 +1,12 @@
---
title: BlackDuck
author: Deepankumar
authorUrl: https://github.com/deepan10
category: Security
description: BlackDuck scanned vulnerabilities in Backstage.
documentation: https://github.com/deepan10/backstage-plugin-blackduck
iconUrl: https://avatars.githubusercontent.com/u/431461?s=200&v=4
npmPackageName: '@deepan10/backstage-plugin-blackduck'
tags:
- security
addedDate: '2022-12-03'
@@ -0,0 +1,13 @@
---
title: CI/CD Statistics
author: Spotify
authorUrl: https://github.com/spotify
category: CI/CD
description: Visualize CI/CD pipeline statistics such as build time or success and error rates.
documentation: https://github.com/backstage/backstage/tree/master/plugins/cicd-statistics
iconUrl: img/cicd-statistics.svg
npmPackageName: '@backstage/plugin-cicd-statistics'
tags:
- ci
- cd
addedDate: '2022-01-13'
+13
View File
@@ -0,0 +1,13 @@
---
title: Harness CI/CD
author: harness.io
authorUrl: https://github.com/harness/backstage-plugins
category: CI/CD
description: This plugin lets you view Harness pipeline execution details inside Backstage.
documentation: https://github.com/harness/backstage-plugins/tree/main/plugins/harness-ci-cd
iconUrl: https://static.harness.io/ng-static/images/favicon.png
npmPackageName: '@harnessio/backstage-plugin-ci-cd'
tags:
- ci
- cd
addedDate: '2022-12-08'
+15 -7
View File
@@ -45,13 +45,21 @@ class Index extends React.Component {
ship high-quality code quickly without compromising
autonomy.
</Block.Paragraph>
<Block.LinkButton
href={
'https://github.com/backstage/backstage#getting-started'
}
>
GitHub
</Block.LinkButton>
<Block.Container wrapped>
<Block.LinkButton
style={{ marginRight: '2rem' }}
href={
'https://github.com/backstage/backstage#getting-started'
}
>
GitHub
</Block.LinkButton>
<Block.LinkButton
href={'https://info.backstage.spotify.com/office-hours'}
>
Office Hours
</Block.LinkButton>
</Block.Container>
</Block.TextBox>
<Block.Graphics>
<Block.Graphic
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M21,8c-1.45,0-2.26,1.44-1.93,2.51l-3.55,3.56c-0.3-0.09-0.74-0.09-1.04,0l-2.55-2.55C12.27,10.45,11.46,9,10,9 c-1.45,0-2.27,1.44-1.93,2.52l-4.56,4.55C2.44,15.74,1,16.55,1,18c0,1.1,0.9,2,2,2c1.45,0,2.26-1.44,1.93-2.51l4.55-4.56 c0.3,0.09,0.74,0.09,1.04,0l2.55,2.55C12.73,16.55,13.54,18,15,18c1.45,0,2.27-1.44,1.93-2.52l3.56-3.55 C21.56,12.26,23,11.45,23,10C23,8.9,22.1,8,21,8z"/><polygon points="15,9 15.94,6.93 18,6 15.94,5.07 15,3 14.08,5.07 12,6 14.08,6.93"/><polygon points="3.5,11 4,9 6,8.5 4,8 3.5,6 3,8 1,8.5 3,9"/></g></g></svg>

After

Width:  |  Height:  |  Size: 733 B

+178 -196
View File
@@ -1360,13 +1360,13 @@ __metadata:
languageName: node
linkType: hard
"accepts@npm:~1.3.7":
version: 1.3.7
resolution: "accepts@npm:1.3.7"
"accepts@npm:~1.3.8":
version: 1.3.8
resolution: "accepts@npm:1.3.8"
dependencies:
mime-types: ~2.1.24
negotiator: 0.6.2
checksum: 27fc8060ffc69481ff6719cd3ee06387d2b88381cb0ce626f087781bbd02201a645a9febc8e7e7333558354b33b1d2f922ad13560be4ec1b7ba9e76fc1c1241d
mime-types: ~2.1.34
negotiator: 0.6.3
checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4
languageName: node
linkType: hard
@@ -1906,21 +1906,23 @@ __metadata:
languageName: node
linkType: hard
"body-parser@npm:1.19.0":
version: 1.19.0
resolution: "body-parser@npm:1.19.0"
"body-parser@npm:1.20.1":
version: 1.20.1
resolution: "body-parser@npm:1.20.1"
dependencies:
bytes: 3.1.0
bytes: 3.1.2
content-type: ~1.0.4
debug: 2.6.9
depd: ~1.1.2
http-errors: 1.7.2
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: ~2.3.0
qs: 6.7.0
raw-body: 2.4.0
type-is: ~1.6.17
checksum: 490231b4c89bbd43112762f7ba8e5342c174a6c9f64284a3b0fcabf63277e332f8316765596f1e5b15e4f3a6cf0422e005f4bb3149ed3a224bb025b7a36b9ac1
on-finished: 2.4.1
qs: 6.11.0
raw-body: 2.5.1
type-is: ~1.6.18
unpipe: 1.0.0
checksum: f1050dbac3bede6a78f0b87947a8d548ce43f91ccc718a50dd774f3c81f2d8b04693e52acf62659fad23101827dd318da1fb1363444ff9a8482b886a3e4a5266
languageName: node
linkType: hard
@@ -2063,10 +2065,10 @@ __metadata:
languageName: node
linkType: hard
"bytes@npm:3.1.0":
version: 3.1.0
resolution: "bytes@npm:3.1.0"
checksum: 7c3b21c5d9d44ed455460d5d36a31abc6fa2ce3807964ba60a4b03fd44454c8cf07bb0585af83bfde1c5cc2ea4bbe5897bc3d18cd15e0acf25a3615a35aba2df
"bytes@npm:3.1.2":
version: 3.1.2
resolution: "bytes@npm:3.1.2"
checksum: e4bcd3948d289c5127591fbedf10c0b639ccbf00243504e4e127374a15c3bc8eed0d28d4aaab08ff6f1cf2abc0cce6ba3085ed32f4f90e82a5683ce0014e1b6e
languageName: node
linkType: hard
@@ -2566,12 +2568,12 @@ __metadata:
languageName: node
linkType: hard
"content-disposition@npm:0.5.3, content-disposition@npm:^0.5.2":
version: 0.5.3
resolution: "content-disposition@npm:0.5.3"
"content-disposition@npm:0.5.4, content-disposition@npm:^0.5.2":
version: 0.5.4
resolution: "content-disposition@npm:0.5.4"
dependencies:
safe-buffer: 5.1.2
checksum: 95bf164c0b0b8199d3f44b7631e51b37f683c6a90b9baa4315bd3d405a6d1bc81b7346f0981046aa004331fb3d7a28b629514d01fc209a5251573fc7e4d33380
safe-buffer: 5.2.1
checksum: afb9d545e296a5171d7574fcad634b2fdf698875f4006a9dd04a3e1333880c5c0c98d47b560d01216fb6505a54a2ba6a843ee3a02ec86d7e911e8315255f56c3
languageName: node
linkType: hard
@@ -2605,10 +2607,10 @@ __metadata:
languageName: node
linkType: hard
"cookie@npm:0.4.0":
version: 0.4.0
resolution: "cookie@npm:0.4.0"
checksum: 760384ba0aef329c52523747e36a452b5e51bc49b34160363a6934e7b7df3f93fcc88b35e33450361535d40a92a96412da870e1816aba9aa6cc556a9fedd8492
"cookie@npm:0.5.0":
version: 0.5.0
resolution: "cookie@npm:0.5.0"
checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180
languageName: node
linkType: hard
@@ -3076,17 +3078,24 @@ __metadata:
languageName: node
linkType: hard
"depd@npm:^1.1.2, depd@npm:~1.1.2":
"depd@npm:2.0.0":
version: 2.0.0
resolution: "depd@npm:2.0.0"
checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a
languageName: node
linkType: hard
"depd@npm:^1.1.2":
version: 1.1.2
resolution: "depd@npm:1.1.2"
checksum: 6b406620d269619852885ce15965272b829df6f409724415e0002c8632ab6a8c0a08ec1f0bd2add05dc7bd7507606f7e2cc034fa24224ab829580040b835ecd9
languageName: node
linkType: hard
"destroy@npm:~1.0.4":
version: 1.0.4
resolution: "destroy@npm:1.0.4"
checksum: da9ab4961dc61677c709da0c25ef01733042614453924d65636a7db37308fef8a24cd1e07172e61173d471ca175371295fbc984b0af5b2b4ff47cd57bd784c03
"destroy@npm:1.2.0":
version: 1.2.0
resolution: "destroy@npm:1.2.0"
checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38
languageName: node
linkType: hard
@@ -3611,40 +3620,41 @@ __metadata:
linkType: hard
"express@npm:^4.17.1":
version: 4.17.1
resolution: "express@npm:4.17.1"
version: 4.18.2
resolution: "express@npm:4.18.2"
dependencies:
accepts: ~1.3.7
accepts: ~1.3.8
array-flatten: 1.1.1
body-parser: 1.19.0
content-disposition: 0.5.3
body-parser: 1.20.1
content-disposition: 0.5.4
content-type: ~1.0.4
cookie: 0.4.0
cookie: 0.5.0
cookie-signature: 1.0.6
debug: 2.6.9
depd: ~1.1.2
depd: 2.0.0
encodeurl: ~1.0.2
escape-html: ~1.0.3
etag: ~1.8.1
finalhandler: ~1.1.2
finalhandler: 1.2.0
fresh: 0.5.2
http-errors: 2.0.0
merge-descriptors: 1.0.1
methods: ~1.1.2
on-finished: ~2.3.0
on-finished: 2.4.1
parseurl: ~1.3.3
path-to-regexp: 0.1.7
proxy-addr: ~2.0.5
qs: 6.7.0
proxy-addr: ~2.0.7
qs: 6.11.0
range-parser: ~1.2.1
safe-buffer: 5.1.2
send: 0.17.1
serve-static: 1.14.1
setprototypeof: 1.1.1
statuses: ~1.5.0
safe-buffer: 5.2.1
send: 0.18.0
serve-static: 1.15.0
setprototypeof: 1.2.0
statuses: 2.0.1
type-is: ~1.6.18
utils-merge: 1.0.1
vary: ~1.1.2
checksum: d964e9e17af331ea6fa2f84999b063bc47189dd71b4a735df83f9126d3bb2b92e830f1cb1d7c2742530eb625e2689d7a9a9c71f0c3cc4dd6015c3cd32a01abd5
checksum: 3c4b9b076879442f6b968fe53d85d9f1eeacbb4f4c41e5f16cc36d77ce39a2b0d81b3f250514982110d815b2f7173f5561367f9110fcc541f9371948e8c8b037
languageName: node
linkType: hard
@@ -3916,18 +3926,18 @@ __metadata:
languageName: node
linkType: hard
"finalhandler@npm:~1.1.2":
version: 1.1.2
resolution: "finalhandler@npm:1.1.2"
"finalhandler@npm:1.2.0":
version: 1.2.0
resolution: "finalhandler@npm:1.2.0"
dependencies:
debug: 2.6.9
encodeurl: ~1.0.2
escape-html: ~1.0.3
on-finished: ~2.3.0
on-finished: 2.4.1
parseurl: ~1.3.3
statuses: ~1.5.0
statuses: 2.0.1
unpipe: ~1.0.0
checksum: 617880460c5138dd7ccfd555cb5dde4d8f170f4b31b8bd51e4b646bb2946c30f7db716428a1f2882d730d2b72afb47d1f67cc487b874cb15426f95753a88965e
checksum: 92effbfd32e22a7dff2994acedbd9bcc3aa646a3e919ea6a53238090e87097f8ef07cced90aa2cc421abdf993aefbdd5b00104d55c7c5479a8d00ed105b45716
languageName: node
linkType: hard
@@ -4020,10 +4030,10 @@ __metadata:
languageName: node
linkType: hard
"forwarded@npm:~0.1.2":
version: 0.1.2
resolution: "forwarded@npm:0.1.2"
checksum: 54695c574292f9bc6bfa52111844337bc2e61cfcc5ec82f16b816d721a67a0c76b4849a34b57e38e51d64ddbb81aef974f393579f610ed1b990470e75abad2e0
"forwarded@npm:0.2.0":
version: 0.2.0
resolution: "forwarded@npm:0.2.0"
checksum: fd27e2394d8887ebd16a66ffc889dc983fbbd797d5d3f01087c020283c0f019a7d05ee85669383d8e0d216b116d720fc0cef2f6e9b7eb9f4c90c6e0bc7fd28e6
languageName: node
linkType: hard
@@ -4148,14 +4158,14 @@ __metadata:
languageName: node
linkType: hard
"get-intrinsic@npm:^1.0.0":
version: 1.0.2
resolution: "get-intrinsic@npm:1.0.2"
"get-intrinsic@npm:^1.0.0, get-intrinsic@npm:^1.0.2":
version: 1.1.3
resolution: "get-intrinsic@npm:1.1.3"
dependencies:
function-bind: ^1.1.1
has: ^1.0.3
has-symbols: ^1.0.1
checksum: bed41c7426212d79982c23e9dddb7de2b6b05ca35e94e653edfed06188381ed4eae0e04adf7f4d3ea1f47f1c345b255405e8c44b1167185537a506eff5c519c8
has-symbols: ^1.0.3
checksum: 152d79e87251d536cf880ba75cfc3d6c6c50e12b3a64e1ea960e73a3752b47c69f46034456eae1b0894359ce3bc64c55c186f2811f8a788b75b638b06fab228a
languageName: node
linkType: hard
@@ -4486,10 +4496,10 @@ __metadata:
languageName: node
linkType: hard
"has-symbols@npm:^1.0.1":
version: 1.0.1
resolution: "has-symbols@npm:1.0.1"
checksum: 4f09be6682f9fc29855ded1101ad2a0f5d559d7d9ed68f7b68be1ea213c23991216d08d6585bf3ff6fded6f526cc506bda528d276f083602b55d232f132cfa27
"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.3":
version: 1.0.3
resolution: "has-symbols@npm:1.0.3"
checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410
languageName: node
linkType: hard
@@ -4627,29 +4637,16 @@ __metadata:
languageName: node
linkType: hard
"http-errors@npm:1.7.2":
version: 1.7.2
resolution: "http-errors@npm:1.7.2"
"http-errors@npm:2.0.0":
version: 2.0.0
resolution: "http-errors@npm:2.0.0"
dependencies:
depd: ~1.1.2
inherits: 2.0.3
setprototypeof: 1.1.1
statuses: ">= 1.5.0 < 2"
toidentifier: 1.0.0
checksum: 5534b0ae08e77f5a45a2380f500e781f6580c4ff75b816cb1f09f99a290b57e78a518be6d866db1b48cca6b052c09da2c75fc91fb16a2fe3da3c44d9acbb9972
languageName: node
linkType: hard
"http-errors@npm:~1.7.2":
version: 1.7.3
resolution: "http-errors@npm:1.7.3"
dependencies:
depd: ~1.1.2
depd: 2.0.0
inherits: 2.0.4
setprototypeof: 1.1.1
statuses: ">= 1.5.0 < 2"
toidentifier: 1.0.0
checksum: a59f359473f4b3ea78305beee90d186268d6075432622a46fb7483059068a2dd4c854a20ac8cd438883127e06afb78c1309168bde6cdfeed1e3700eb42487d99
setprototypeof: 1.2.0
statuses: 2.0.1
toidentifier: 1.0.1
checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920
languageName: node
linkType: hard
@@ -4868,13 +4865,6 @@ __metadata:
languageName: node
linkType: hard
"inherits@npm:2.0.3":
version: 2.0.3
resolution: "inherits@npm:2.0.3"
checksum: 78cb8d7d850d20a5e9a7f3620db31483aa00ad5f722ce03a55b110e5a723539b3716a3b463e2b96ce3fe286f33afc7c131fa2f91407528ba80cea98a7545d4c0
languageName: node
linkType: hard
"ini@npm:^1.3.4, ini@npm:^1.3.5":
version: 1.3.8
resolution: "ini@npm:1.3.8"
@@ -6109,19 +6099,19 @@ __metadata:
languageName: node
linkType: hard
"mime-db@npm:1.45.0, mime-db@npm:^1.28.0":
version: 1.45.0
resolution: "mime-db@npm:1.45.0"
checksum: 00aa67af7a2014c12380bec57b3efe988e45c51979acca792633e2ba4d45c601b4160ceaf9666e2b8fa6822f5cb81e12206f9921d1bc3d78226aee813d4244fd
"mime-db@npm:1.52.0, mime-db@npm:^1.28.0":
version: 1.52.0
resolution: "mime-db@npm:1.52.0"
checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f
languageName: node
linkType: hard
"mime-types@npm:^2.1.12, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24":
version: 2.1.28
resolution: "mime-types@npm:2.1.28"
"mime-types@npm:^2.1.12, mime-types@npm:~2.1.19, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
dependencies:
mime-db: 1.45.0
checksum: ea59cb885b5234cd7fcc2c8de1eff8543cf057be7daaf804a1b9b2cc6930c8dbcdc5e86b9732827a794d5282baa6f45ef93bc50eaba93839b9174cc6d36c9702
mime-db: 1.52.0
checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836
languageName: node
linkType: hard
@@ -6289,13 +6279,6 @@ __metadata:
languageName: node
linkType: hard
"ms@npm:2.1.1":
version: 2.1.1
resolution: "ms@npm:2.1.1"
checksum: 0078a23cd916a9a7435c413caa14c57d4b4f6e2470e0ab554b6964163c8a4436448ac7ae020e883685475da6b6796cc396b670f579cb275db288a21e3e57721e
languageName: node
linkType: hard
"ms@npm:2.1.2":
version: 2.1.2
resolution: "ms@npm:2.1.2"
@@ -6303,7 +6286,7 @@ __metadata:
languageName: node
linkType: hard
"ms@npm:^2.0.0, ms@npm:^2.1.1":
"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
@@ -6345,14 +6328,7 @@ __metadata:
languageName: node
linkType: hard
"negotiator@npm:0.6.2":
version: 0.6.2
resolution: "negotiator@npm:0.6.2"
checksum: dfddaff6c06792f1c4c3809e29a427b8daef8cd437c83b08dd51d7ee11bbd1c29d9512d66b801144d6c98e910ffd8723f2432e0cbf8b18d41d2a09599c975ab3
languageName: node
linkType: hard
"negotiator@npm:^0.6.3":
"negotiator@npm:0.6.3, negotiator@npm:^0.6.3":
version: 0.6.3
resolution: "negotiator@npm:0.6.3"
checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9
@@ -6536,10 +6512,10 @@ __metadata:
languageName: node
linkType: hard
"object-inspect@npm:^1.8.0":
version: 1.9.0
resolution: "object-inspect@npm:1.9.0"
checksum: 715d2ef5beebfecd5c6d5b29dd370b11bb37d46284d4c1e38463c1ab5dd182cb9d1b543b3f0ea682c84a1883863ea2fe6e6b7599a65a6ab043545189b06e8800
"object-inspect@npm:^1.8.0, object-inspect@npm:^1.9.0":
version: 1.12.2
resolution: "object-inspect@npm:1.12.2"
checksum: a534fc1b8534284ed71f25ce3a496013b7ea030f3d1b77118f6b7b1713829262be9e6243acbcb3ef8c626e2b64186112cb7f6db74e37b2789b9c789ca23048b2
languageName: node
linkType: hard
@@ -6603,12 +6579,12 @@ __metadata:
languageName: node
linkType: hard
"on-finished@npm:~2.3.0":
version: 2.3.0
resolution: "on-finished@npm:2.3.0"
"on-finished@npm:2.4.1":
version: 2.4.1
resolution: "on-finished@npm:2.4.1"
dependencies:
ee-first: 1.1.1
checksum: 1db595bd963b0124d6fa261d18320422407b8f01dc65863840f3ddaaf7bcad5b28ff6847286703ca53f4ec19595bd67a2f1253db79fc4094911ec6aa8df1671b
checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0
languageName: node
linkType: hard
@@ -7393,11 +7369,11 @@ __metadata:
linkType: hard
"prettier@npm:^2.6.2":
version: 2.8.0
resolution: "prettier@npm:2.8.0"
version: 2.8.1
resolution: "prettier@npm:2.8.1"
bin:
prettier: bin-prettier.js
checksum: 72004ce0cc9bb097daf3e3833f62495768724392c1d5b178dd47372337616e9e50ecbb0804f236596223f7b5eb1bbe69cefc8957dca21112c5777e77ef73a564
checksum: 4f21a0f1269f76fb36f54e9a8a1ea4c11e27478958bf860661fb4b6d7ac69aac1581f8724fa98ea3585e56d42a2ea317a17ff6e3324f40cb11ff9e20b73785cc
languageName: node
linkType: hard
@@ -7450,13 +7426,13 @@ __metadata:
languageName: node
linkType: hard
"proxy-addr@npm:~2.0.5":
version: 2.0.6
resolution: "proxy-addr@npm:2.0.6"
"proxy-addr@npm:~2.0.7":
version: 2.0.7
resolution: "proxy-addr@npm:2.0.7"
dependencies:
forwarded: ~0.1.2
forwarded: 0.2.0
ipaddr.js: 1.9.1
checksum: 2bad9b7a56b847faf606a19328aaaf5fca3e561ebb4e933969a580d94a20f77e74fb21196028a6e417851b3d9d95a0c704732a3362e3ef515d45d96859ac7eb9
checksum: 29c6990ce9364648255454842f06f8c46fcd124d3e6d7c5066df44662de63cdc0bad032e9bf5a3d653ff72141cc7b6019873d685708ac8210c30458ad99f2b74
languageName: node
linkType: hard
@@ -7498,24 +7474,19 @@ __metadata:
languageName: node
linkType: hard
"qs@npm:6.7.0":
version: 6.7.0
resolution: "qs@npm:6.7.0"
checksum: dfd5f6adef50e36e908cfa70a6233871b5afe66fbaca37ecc1da352ba29eb2151a3797991948f158bb37fccde51bd57845cb619a8035287bfc24e4591172c347
languageName: node
linkType: hard
"qs@npm:^6.4.0":
version: 6.9.4
resolution: "qs@npm:6.9.4"
checksum: 5ac0bd145f32d346d20c2fdcf19c8e548c5916458851e32527efb25be0c2cff8a3a81140c145c98a1184779b5b625c91bc7c50e147073bffb978fb7f4a9c8c8a
"qs@npm:6.11.0, qs@npm:^6.4.0":
version: 6.11.0
resolution: "qs@npm:6.11.0"
dependencies:
side-channel: ^1.0.4
checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297
languageName: node
linkType: hard
"qs@npm:~6.5.2":
version: 6.5.2
resolution: "qs@npm:6.5.2"
checksum: 24af7b9928ba2141233fba2912876ff100403dba1b08b20c3b490da9ea6c636760445ea2211a079e7dfa882a5cf8f738337b3748c8bdd0f93358fa8881d2db8f
version: 6.5.3
resolution: "qs@npm:6.5.3"
checksum: 6f20bf08cabd90c458e50855559539a28d00b2f2e7dddcb66082b16a43188418cb3cb77cbd09268bcef6022935650f0534357b8af9eeb29bf0f27ccb17655692
languageName: node
linkType: hard
@@ -7555,15 +7526,15 @@ __metadata:
languageName: node
linkType: hard
"raw-body@npm:2.4.0":
version: 2.4.0
resolution: "raw-body@npm:2.4.0"
"raw-body@npm:2.5.1":
version: 2.5.1
resolution: "raw-body@npm:2.5.1"
dependencies:
bytes: 3.1.0
http-errors: 1.7.2
bytes: 3.1.2
http-errors: 2.0.0
iconv-lite: 0.4.24
unpipe: 1.0.0
checksum: 6343906939e018c6e633a34a938a5d6d1e93ffcfa48646e00207d53b418e941953b521473950c079347220944dc75ba10e7b3c08bf97e3ac72c7624882db09bb
checksum: 5362adff1575d691bb3f75998803a0ffed8c64eabeaa06e54b4ada25a0cd1b2ae7f4f5ec46565d1bec337e08b5ac90c76eaa0758de6f72a633f025d754dec29e
languageName: node
linkType: hard
@@ -8030,20 +8001,20 @@ __metadata:
languageName: node
linkType: hard
"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1":
version: 5.1.2
resolution: "safe-buffer@npm:5.1.2"
checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c
languageName: node
linkType: hard
"safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0":
"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491
languageName: node
linkType: hard
"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1":
version: 5.1.2
resolution: "safe-buffer@npm:5.1.2"
checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c
languageName: node
linkType: hard
"safe-json-parse@npm:~1.0.1":
version: 1.0.1
resolution: "safe-json-parse@npm:1.0.1"
@@ -8141,36 +8112,36 @@ __metadata:
languageName: node
linkType: hard
"send@npm:0.17.1":
version: 0.17.1
resolution: "send@npm:0.17.1"
"send@npm:0.18.0":
version: 0.18.0
resolution: "send@npm:0.18.0"
dependencies:
debug: 2.6.9
depd: ~1.1.2
destroy: ~1.0.4
depd: 2.0.0
destroy: 1.2.0
encodeurl: ~1.0.2
escape-html: ~1.0.3
etag: ~1.8.1
fresh: 0.5.2
http-errors: ~1.7.2
http-errors: 2.0.0
mime: 1.6.0
ms: 2.1.1
on-finished: ~2.3.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: ~1.2.1
statuses: ~1.5.0
checksum: d214c2fa42e7fae3f8fc1aa3931eeb3e6b78c2cf141574e09dbe159915c1e3a337269fc6b7512e7dfddcd7d6ff5974cb62f7c3637ba86a55bde20a92c18bdca0
statuses: 2.0.1
checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8
languageName: node
linkType: hard
"serve-static@npm:1.14.1":
version: 1.14.1
resolution: "serve-static@npm:1.14.1"
"serve-static@npm:1.15.0":
version: 1.15.0
resolution: "serve-static@npm:1.15.0"
dependencies:
encodeurl: ~1.0.2
escape-html: ~1.0.3
parseurl: ~1.3.3
send: 0.17.1
checksum: c6b268e8486d39ecd54b86c7f2d0ee4a38cd7514ddd9c92c8d5793bb005afde5e908b12395898ae206782306ccc848193d93daa15b86afb3cbe5a8414806abe8
send: 0.18.0
checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d
languageName: node
linkType: hard
@@ -8202,10 +8173,10 @@ __metadata:
languageName: node
linkType: hard
"setprototypeof@npm:1.1.1":
version: 1.1.1
resolution: "setprototypeof@npm:1.1.1"
checksum: a8bee29c1c64c245d460ce53f7460af8cbd0aceac68d66e5215153992cc8b3a7a123416353e0c642060e85cc5fd4241c92d1190eec97eda0dcb97436e8fcca3b
"setprototypeof@npm:1.2.0":
version: 1.2.0
resolution: "setprototypeof@npm:1.2.0"
checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89
languageName: node
linkType: hard
@@ -8245,6 +8216,17 @@ __metadata:
languageName: node
linkType: hard
"side-channel@npm:^1.0.4":
version: 1.0.4
resolution: "side-channel@npm:1.0.4"
dependencies:
call-bind: ^1.0.0
get-intrinsic: ^1.0.2
object-inspect: ^1.9.0
checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245
languageName: node
linkType: hard
"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7":
version: 3.0.7
resolution: "signal-exit@npm:3.0.7"
@@ -8537,10 +8519,10 @@ __metadata:
languageName: node
linkType: hard
"statuses@npm:>= 1.5.0 < 2, statuses@npm:~1.5.0":
version: 1.5.0
resolution: "statuses@npm:1.5.0"
checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c
"statuses@npm:2.0.1":
version: 2.0.1
resolution: "statuses@npm:2.0.1"
checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb
languageName: node
linkType: hard
@@ -8947,10 +8929,10 @@ __metadata:
languageName: node
linkType: hard
"toidentifier@npm:1.0.0":
version: 1.0.0
resolution: "toidentifier@npm:1.0.0"
checksum: 199e6bfca1531d49b3506cff02353d53ec987c9ee10ee272ca6484ed97f1fc10fb77c6c009079ca16d5c5be4a10378178c3cacdb41ce9ec954c3297c74c6053e
"toidentifier@npm:1.0.1":
version: 1.0.1
resolution: "toidentifier@npm:1.0.1"
checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45
languageName: node
linkType: hard
@@ -9041,7 +9023,7 @@ __metadata:
languageName: node
linkType: hard
"type-is@npm:~1.6.17, type-is@npm:~1.6.18":
"type-is@npm:~1.6.18":
version: 1.6.18
resolution: "type-is@npm:1.6.18"
dependencies:
+1 -1
View File
@@ -46,7 +46,7 @@
"@types/react": "^17",
"@types/react-dom": "^17"
},
"version": "1.9.0-next.1",
"version": "1.9.0-next.3",
"dependencies": {
"@backstage/errors": "workspace:^",
"@manypkg/get-packages": "^1.1.3"
+22
View File
@@ -1,5 +1,27 @@
# @backstage/app-defaults
## 1.0.9-next.3
### Patch Changes
- Updated dependencies
- @backstage/core-app-api@1.2.1-next.3
- @backstage/core-components@0.12.1-next.3
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/theme@0.2.16
- @backstage/plugin-permission-react@0.4.8-next.2
## 1.0.9-next.2
### Patch Changes
- Updated dependencies
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/core-app-api@1.2.1-next.2
- @backstage/core-components@0.12.1-next.2
- @backstage/plugin-permission-react@0.4.8-next.2
- @backstage/theme@0.2.16
## 1.0.9-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/app-defaults",
"description": "Provides the default wiring of a Backstage App",
"version": "1.0.9-next.1",
"version": "1.0.9-next.3",
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
+126
View File
@@ -1,5 +1,131 @@
# example-app
## 0.2.78-next.3
### Patch Changes
- Updated dependencies
- @backstage/cli@0.21.2-next.3
- @backstage/core-app-api@1.2.1-next.3
- @backstage/plugin-airbrake@0.3.12-next.3
- @backstage/core-components@0.12.1-next.3
- @backstage/app-defaults@1.0.9-next.3
- @backstage/catalog-model@1.1.4-next.1
- @backstage/config@1.0.5-next.1
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/integration-react@1.1.7-next.3
- @backstage/theme@0.2.16
- @backstage/plugin-apache-airflow@0.2.5-next.3
- @backstage/plugin-api-docs@0.8.12-next.3
- @backstage/plugin-azure-devops@0.2.3-next.3
- @backstage/plugin-azure-sites@0.1.1-next.3
- @backstage/plugin-badges@0.2.36-next.3
- @backstage/plugin-catalog-common@1.0.9-next.2
- @backstage/plugin-catalog-graph@0.2.24-next.3
- @backstage/plugin-catalog-import@0.9.2-next.3
- @backstage/plugin-catalog-react@1.2.2-next.3
- @backstage/plugin-circleci@0.3.12-next.3
- @backstage/plugin-cloudbuild@0.3.12-next.3
- @backstage/plugin-code-coverage@0.2.5-next.3
- @backstage/plugin-cost-insights@0.12.1-next.3
- @backstage/plugin-dynatrace@1.0.2-next.3
- @backstage/plugin-explore@0.3.43-next.3
- @backstage/plugin-gcalendar@0.3.8-next.3
- @backstage/plugin-gcp-projects@0.3.31-next.3
- @backstage/plugin-github-actions@0.5.12-next.3
- @backstage/plugin-gocd@0.1.18-next.3
- @backstage/plugin-graphiql@0.2.44-next.3
- @backstage/plugin-home@0.4.28-next.3
- @backstage/plugin-jenkins@0.7.11-next.3
- @backstage/plugin-kafka@0.3.12-next.3
- @backstage/plugin-kubernetes@0.7.5-next.3
- @backstage/plugin-lighthouse@0.3.12-next.3
- @backstage/plugin-newrelic@0.3.30-next.3
- @backstage/plugin-newrelic-dashboard@0.2.5-next.3
- @backstage/plugin-org@0.6.2-next.3
- @backstage/plugin-pagerduty@0.5.5-next.3
- @backstage/plugin-permission-react@0.4.8-next.2
- @backstage/plugin-playlist@0.1.3-next.3
- @backstage/plugin-rollbar@0.4.12-next.3
- @backstage/plugin-scaffolder@1.9.0-next.3
- @backstage/plugin-search@1.0.5-next.3
- @backstage/plugin-search-common@1.2.0-next.2
- @backstage/plugin-search-react@1.3.0-next.3
- @backstage/plugin-sentry@0.4.5-next.3
- @backstage/plugin-shortcuts@0.3.4-next.3
- @backstage/plugin-stack-overflow@0.1.8-next.3
- @backstage/plugin-tech-insights@0.3.4-next.3
- @backstage/plugin-tech-radar@0.5.19-next.3
- @backstage/plugin-techdocs@1.4.1-next.3
- @backstage/plugin-techdocs-module-addons-contrib@1.0.7-next.3
- @backstage/plugin-techdocs-react@1.0.7-next.3
- @backstage/plugin-todo@0.2.14-next.3
- @backstage/plugin-user-settings@0.6.0-next.3
- @internal/plugin-catalog-customized@0.0.5-next.3
## 0.2.78-next.2
### Patch Changes
- Updated dependencies
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/plugin-search-react@1.3.0-next.2
- @backstage/plugin-explore@0.3.43-next.2
- @backstage/cli@0.21.2-next.2
- @backstage/core-app-api@1.2.1-next.2
- @backstage/core-components@0.12.1-next.2
- @backstage/plugin-catalog-react@1.2.2-next.2
- @backstage/plugin-cost-insights@0.12.1-next.2
- @backstage/plugin-gcp-projects@0.3.31-next.2
- @backstage/plugin-scaffolder@1.9.0-next.2
- @backstage/plugin-techdocs-module-addons-contrib@1.0.7-next.2
- @backstage/plugin-catalog-graph@0.2.24-next.2
- @backstage/plugin-search-common@1.2.0-next.2
- @backstage/plugin-api-docs@0.8.12-next.2
- @internal/plugin-catalog-customized@0.0.5-next.2
- @backstage/app-defaults@1.0.9-next.2
- @backstage/integration-react@1.1.7-next.2
- @backstage/plugin-airbrake@0.3.12-next.2
- @backstage/plugin-apache-airflow@0.2.5-next.2
- @backstage/plugin-azure-devops@0.2.3-next.2
- @backstage/plugin-azure-sites@0.1.1-next.2
- @backstage/plugin-badges@0.2.36-next.2
- @backstage/plugin-catalog-import@0.9.2-next.2
- @backstage/plugin-circleci@0.3.12-next.2
- @backstage/plugin-cloudbuild@0.3.12-next.2
- @backstage/plugin-code-coverage@0.2.5-next.2
- @backstage/plugin-dynatrace@1.0.2-next.2
- @backstage/plugin-gcalendar@0.3.8-next.2
- @backstage/plugin-github-actions@0.5.12-next.2
- @backstage/plugin-gocd@0.1.18-next.2
- @backstage/plugin-graphiql@0.2.44-next.2
- @backstage/plugin-home@0.4.28-next.2
- @backstage/plugin-jenkins@0.7.11-next.2
- @backstage/plugin-kafka@0.3.12-next.2
- @backstage/plugin-kubernetes@0.7.5-next.2
- @backstage/plugin-lighthouse@0.3.12-next.2
- @backstage/plugin-newrelic@0.3.30-next.2
- @backstage/plugin-newrelic-dashboard@0.2.5-next.2
- @backstage/plugin-org@0.6.2-next.2
- @backstage/plugin-pagerduty@0.5.5-next.2
- @backstage/plugin-permission-react@0.4.8-next.2
- @backstage/plugin-playlist@0.1.3-next.2
- @backstage/plugin-rollbar@0.4.12-next.2
- @backstage/plugin-search@1.0.5-next.2
- @backstage/plugin-sentry@0.4.5-next.2
- @backstage/plugin-shortcuts@0.3.4-next.2
- @backstage/plugin-stack-overflow@0.1.8-next.2
- @backstage/plugin-tech-insights@0.3.4-next.2
- @backstage/plugin-tech-radar@0.5.19-next.2
- @backstage/plugin-techdocs@1.4.1-next.2
- @backstage/plugin-techdocs-react@1.0.7-next.2
- @backstage/plugin-todo@0.2.14-next.2
- @backstage/plugin-user-settings@0.6.0-next.2
- @backstage/catalog-model@1.1.4-next.1
- @backstage/config@1.0.5-next.1
- @backstage/theme@0.2.16
- @backstage/plugin-catalog-common@1.0.9-next.2
## 0.2.78-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-app",
"version": "0.2.78-next.1",
"version": "0.2.78-next.3",
"private": true,
"backstage": {
"role": "frontend"
+1 -1
View File
@@ -280,7 +280,7 @@ const routes = (
const App = () => (
<AppProvider>
<AlertDisplay />
<AlertDisplay transientTimeoutMs={2500} />
<OAuthRequestDialog />
<AppRouter>
<Root>{routes}</Root>
+12
View File
@@ -1,5 +1,17 @@
# @backstage/backend-app-api
## 0.2.4-next.2
### Patch Changes
- 884d749b14: Refactored to use `coreServices` from `@backstage/backend-plugin-api`.
- Updated dependencies
- @backstage/backend-common@0.17.0-next.2
- @backstage/backend-plugin-api@0.2.0-next.2
- @backstage/backend-tasks@0.4.0-next.2
- @backstage/plugin-permission-node@0.7.2-next.2
- @backstage/errors@1.1.4-next.1
## 0.2.4-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-app-api",
"description": "Core API used by Backstage backend apps",
"version": "0.2.4-next.1",
"version": "0.2.4-next.2",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+16
View File
@@ -1,5 +1,21 @@
# @backstage/backend-common
## 0.17.0-next.2
### Patch Changes
- 98776e638a: Fixed GitlabUrlReader to include api tokens in API calls
- 20a5161f04: Adds MySQL support for the catalog-backend
- 3c1302c07d: Updated dependency `@types/http-errors` to `^2.0.0`.
- 8015ff1258: Tweaked wording to use inclusive terminology
- Updated dependencies
- @backstage/cli-common@0.1.11-next.0
- @backstage/config@1.0.5-next.1
- @backstage/config-loader@1.1.7-next.2
- @backstage/errors@1.1.4-next.1
- @backstage/integration@1.4.1-next.1
- @backstage/types@1.0.2-next.1
## 0.17.0-next.1
### Minor Changes
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-common",
"description": "Common functionality library for Backstage backends",
"version": "0.17.0-next.1",
"version": "0.17.0-next.2",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
@@ -101,7 +101,7 @@
"@types/compression": "^1.7.0",
"@types/concat-stream": "^2.0.0",
"@types/fs-extra": "^9.0.3",
"@types/http-errors": "^1.6.3",
"@types/http-errors": "^2.0.0",
"@types/minimist": "^1.2.0",
"@types/mock-fs": "^4.13.0",
"@types/morgan": "^1.9.0",
@@ -44,6 +44,7 @@ const gitlabProcessor = new GitlabUrlReader(
host: 'gitlab.com',
apiBaseUrl: 'https://gitlab.com/api/v4',
baseUrl: 'https://gitlab.com',
token: 'gl-dummy-token',
}),
),
),
@@ -57,6 +58,7 @@ const hostedGitlabProcessor = new GitlabUrlReader(
host: 'gitlab.mycompany.com',
apiBaseUrl: 'https://gitlab.mycompany.com/api/v4',
baseUrl: 'https://gitlab.mycompany.com',
token: 'gl-dummy-token',
}),
),
),
@@ -656,4 +658,21 @@ describe('GitlabUrlReader', () => {
).rejects.toThrow(/^Unable to translate GitLab artifact URL:/);
});
});
describe('resolveProjectToId', () => {
it('should resolve the project path to a valid project id', async () => {
worker.use(
rest.get('*/api/v4/projects/some%2Fproject', (req, res, ctx) => {
// the private-token header must be included on API calls
expect(req.headers.get('private-token')).toBe('gl-dummy-token');
return res(ctx.status(200), ctx.json({ id: 12345 }));
}),
);
await expect(
(gitlabProcessor as any).resolveProjectToId(
new URL('https://gitlab.com/some/project'),
),
).resolves.toEqual(12345);
});
});
});
@@ -311,6 +311,7 @@ export class GitlabUrlReader implements UrlReader {
`${
pathToProject.origin
}${relativePath}/api/v4/projects/${encodeURIComponent(project)}`,
getGitLabRequestOptions(this.integration.config),
);
const data = await result.json();
if (!result.ok) {
+8
View File
@@ -1,5 +1,13 @@
# @backstage/backend-defaults
## 0.1.4-next.2
### Patch Changes
- Updated dependencies
- @backstage/backend-app-api@0.2.4-next.2
- @backstage/backend-plugin-api@0.2.0-next.2
## 0.1.4-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-defaults",
"description": "Backend defaults used by Backstage backend apps",
"version": "0.1.4-next.1",
"version": "0.1.4-next.2",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+10
View File
@@ -1,5 +1,15 @@
# example-backend-next
## 0.0.6-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-backend@1.6.0-next.2
- @backstage/plugin-app-backend@0.3.39-next.2
- @backstage/plugin-scaffolder-backend@1.9.0-next.2
- @backstage/backend-defaults@0.1.4-next.2
## 0.0.6-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-backend-next",
"version": "0.0.6-next.1",
"version": "0.0.6-next.2",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
+14
View File
@@ -1,5 +1,19 @@
# @backstage/backend-plugin-api
## 0.2.0-next.2
### Minor Changes
- 884d749b14: **BREAKING**: All core service references are now exported via a single `coreServices` object. For example, the `loggerServiceRef` is now accessed via `coreServices.logger` instead.
### Patch Changes
- Updated dependencies
- @backstage/backend-common@0.17.0-next.2
- @backstage/backend-tasks@0.4.0-next.2
- @backstage/config@1.0.5-next.1
- @backstage/plugin-permission-common@0.7.2-next.1
## 0.1.5-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-plugin-api",
"description": "Core API used by Backstage backend plugins",
"version": "0.1.5-next.1",
"version": "0.2.0-next.2",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+10
View File
@@ -1,5 +1,15 @@
# @backstage/backend-tasks
## 0.4.0-next.2
### Patch Changes
- Updated dependencies
- @backstage/backend-common@0.17.0-next.2
- @backstage/config@1.0.5-next.1
- @backstage/errors@1.1.4-next.1
- @backstage/types@1.0.2-next.1
## 0.4.0-next.1
### Minor Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-tasks",
"description": "Common distributed task management library for Backstage backends",
"version": "0.4.0-next.1",
"version": "0.4.0-next.2",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+22
View File
@@ -1,5 +1,27 @@
# @backstage/backend-test-utils
## 0.1.31-next.3
### Patch Changes
- Updated dependencies
- @backstage/cli@0.21.2-next.3
- @backstage/backend-app-api@0.2.4-next.2
- @backstage/backend-common@0.17.0-next.2
- @backstage/backend-plugin-api@0.2.0-next.2
- @backstage/config@1.0.5-next.1
## 0.1.31-next.2
### Patch Changes
- Updated dependencies
- @backstage/backend-app-api@0.2.4-next.2
- @backstage/backend-common@0.17.0-next.2
- @backstage/cli@0.21.2-next.2
- @backstage/backend-plugin-api@0.2.0-next.2
- @backstage/config@1.0.5-next.1
## 0.1.31-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/backend-test-utils",
"description": "Test helpers library for Backstage backends",
"version": "0.1.31-next.1",
"version": "0.1.31-next.3",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+94
View File
@@ -1,5 +1,99 @@
# example-backend
## 0.2.78-next.3
### Patch Changes
- Updated dependencies
- example-app@0.2.78-next.3
- @backstage/backend-common@0.17.0-next.2
- @backstage/backend-tasks@0.4.0-next.2
- @backstage/catalog-client@1.2.0-next.1
- @backstage/catalog-model@1.1.4-next.1
- @backstage/config@1.0.5-next.1
- @backstage/integration@1.4.1-next.1
- @backstage/plugin-app-backend@0.3.39-next.2
- @backstage/plugin-auth-backend@0.17.2-next.2
- @backstage/plugin-auth-node@0.2.8-next.2
- @backstage/plugin-azure-devops-backend@0.3.18-next.2
- @backstage/plugin-azure-sites-backend@0.1.1-next.2
- @backstage/plugin-badges-backend@0.1.33-next.2
- @backstage/plugin-catalog-backend@1.6.0-next.2
- @backstage/plugin-catalog-node@1.3.0-next.2
- @backstage/plugin-code-coverage-backend@0.2.5-next.2
- @backstage/plugin-events-backend@0.2.0-next.2
- @backstage/plugin-events-node@0.2.0-next.2
- @backstage/plugin-explore-backend@0.0.1-next.1
- @backstage/plugin-graphql-backend@0.1.29-next.2
- @backstage/plugin-jenkins-backend@0.1.29-next.2
- @backstage/plugin-kafka-backend@0.2.32-next.2
- @backstage/plugin-kubernetes-backend@0.8.1-next.3
- @backstage/plugin-permission-backend@0.5.14-next.2
- @backstage/plugin-permission-common@0.7.2-next.1
- @backstage/plugin-permission-node@0.7.2-next.2
- @backstage/plugin-playlist-backend@0.2.2-next.3
- @backstage/plugin-proxy-backend@0.2.33-next.2
- @backstage/plugin-rollbar-backend@0.1.36-next.2
- @backstage/plugin-scaffolder-backend@1.9.0-next.2
- @backstage/plugin-scaffolder-backend-module-rails@0.4.7-next.2
- @backstage/plugin-search-backend@1.2.0-next.2
- @backstage/plugin-search-backend-module-elasticsearch@1.1.0-next.2
- @backstage/plugin-search-backend-module-pg@0.4.3-next.2
- @backstage/plugin-search-backend-node@1.1.0-next.2
- @backstage/plugin-search-common@1.2.0-next.2
- @backstage/plugin-tech-insights-backend@0.5.5-next.2
- @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.23-next.2
- @backstage/plugin-tech-insights-node@0.3.7-next.2
- @backstage/plugin-techdocs-backend@1.4.2-next.2
- @backstage/plugin-todo-backend@0.1.36-next.2
## 0.2.78-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-azure-devops-backend@0.3.18-next.2
- @backstage/plugin-search-backend@1.2.0-next.2
- @backstage/plugin-search-backend-module-elasticsearch@1.1.0-next.2
- @backstage/plugin-search-backend-node@1.1.0-next.2
- @backstage/plugin-catalog-backend@1.6.0-next.2
- @backstage/plugin-playlist-backend@0.2.2-next.2
- @backstage/plugin-search-backend-module-pg@0.4.3-next.2
- @backstage/plugin-app-backend@0.3.39-next.2
- @backstage/plugin-catalog-node@1.3.0-next.2
- @backstage/plugin-events-backend@0.2.0-next.2
- @backstage/plugin-scaffolder-backend@1.9.0-next.2
- @backstage/backend-common@0.17.0-next.2
- @backstage/plugin-search-common@1.2.0-next.2
- example-app@0.2.78-next.2
- @backstage/plugin-techdocs-backend@1.4.2-next.2
- @backstage/plugin-scaffolder-backend-module-rails@0.4.7-next.2
- @backstage/backend-tasks@0.4.0-next.2
- @backstage/plugin-auth-backend@0.17.2-next.2
- @backstage/plugin-auth-node@0.2.8-next.2
- @backstage/plugin-azure-sites-backend@0.1.1-next.2
- @backstage/plugin-badges-backend@0.1.33-next.2
- @backstage/plugin-code-coverage-backend@0.2.5-next.2
- @backstage/plugin-explore-backend@0.0.1-next.1
- @backstage/plugin-graphql-backend@0.1.29-next.2
- @backstage/plugin-jenkins-backend@0.1.29-next.2
- @backstage/plugin-kafka-backend@0.2.32-next.2
- @backstage/plugin-kubernetes-backend@0.8.1-next.2
- @backstage/plugin-permission-backend@0.5.14-next.2
- @backstage/plugin-permission-node@0.7.2-next.2
- @backstage/plugin-proxy-backend@0.2.33-next.2
- @backstage/plugin-rollbar-backend@0.1.36-next.2
- @backstage/plugin-tech-insights-backend@0.5.5-next.2
- @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.23-next.2
- @backstage/plugin-tech-insights-node@0.3.7-next.2
- @backstage/plugin-todo-backend@0.1.36-next.2
- @backstage/catalog-client@1.2.0-next.1
- @backstage/catalog-model@1.1.4-next.1
- @backstage/config@1.0.5-next.1
- @backstage/integration@1.4.1-next.1
- @backstage/plugin-events-node@0.2.0-next.2
- @backstage/plugin-permission-common@0.7.2-next.1
## 0.2.78-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-backend",
"version": "0.2.78-next.1",
"version": "0.2.78-next.3",
"main": "dist/index.cjs.js",
"types": "src/index.ts",
"license": "Apache-2.0",
+6
View File
@@ -1,5 +1,11 @@
# @backstage/cli-common
## 0.1.11-next.0
### Patch Changes
- 8015ff1258: Tweaked wording to use inclusive terminology
## 0.1.10
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli-common",
"description": "Common functionality used by cli, backend, and create-app",
"version": "0.1.10",
"version": "0.1.11-next.0",
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
+31
View File
@@ -1,5 +1,36 @@
# @backstage/cli
## 0.21.2-next.3
### Patch Changes
- 43b2b9c791: Removed the unused dependency on `@sucrase/jest-plugin`.
- Updated dependencies
- @backstage/cli-common@0.1.11-next.0
- @backstage/config@1.0.5-next.1
- @backstage/config-loader@1.1.7-next.2
- @backstage/errors@1.1.4-next.1
- @backstage/release-manifests@0.0.8-next.0
- @backstage/types@1.0.2-next.1
## 0.21.2-next.2
### Patch Changes
- 5850ef9b84: Fix webpack dev server issue where it wasn't serving `index.html` from correct endpoint on subsequent requests.
- ee14bab716: Updated dependency `minimatch` to `5.1.1` and switch version range to `^`.
- ed0cf59c59: Updated dependency `@rollup/plugin-commonjs` to `^23.0.0`.
- 16b7c2fccd: Updated dependency `@rollup/plugin-yaml` to `^4.0.0`.
- 086c0bbb45: Updated dependency `@rollup/plugin-json` to `^5.0.0`.
- 8015ff1258: Tweaked wording to use inclusive terminology
- Updated dependencies
- @backstage/cli-common@0.1.11-next.0
- @backstage/config@1.0.5-next.1
- @backstage/config-loader@1.1.7-next.2
- @backstage/errors@1.1.4-next.1
- @backstage/release-manifests@0.0.8-next.0
- @backstage/types@1.0.2-next.1
## 0.21.2-next.1
### Patch Changes
+22 -21
View File
@@ -21,15 +21,10 @@ const glob = require('util').promisify(require('glob'));
const { version } = require('../package.json');
const envOptions = {
nextTests: Boolean(process.env.BACKSTAGE_NEXT_TESTS),
oldTests: Boolean(process.env.BACKSTAGE_OLD_TESTS),
enableSourceMaps: Boolean(process.env.ENABLE_SOURCE_MAPS),
};
if (envOptions.nextTests) {
// Needed so that, at import-time, it can hook into Jest's internals.
require('./jestCachingModuleLoader');
}
const transformIgnorePattern = [
'@material-ui',
'ajv',
@@ -65,7 +60,7 @@ function getRoleConfig(role) {
}
}
async function getProjectConfig(targetPath, displayName) {
async function getProjectConfig(targetPath, extraConfig) {
const configJsPath = path.resolve(targetPath, 'jest.config.js');
const configTsPath = path.resolve(targetPath, 'jest.config.ts');
// If the package has it's own jest config, we use that instead.
@@ -125,11 +120,8 @@ async function getProjectConfig(targetPath, displayName) {
}
const options = {
...(displayName && { displayName }),
...extraConfig,
rootDir: path.resolve(targetPath, 'src'),
coverageDirectory: path.resolve(targetPath, 'coverage'),
coverageProvider: envOptions.nextTests ? 'babel' : 'v8',
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'],
moduleNameMapper: {
'\\.(css|less|scss|sss|styl)$': require.resolve('jest-css-modules'),
},
@@ -138,7 +130,7 @@ async function getProjectConfig(targetPath, displayName) {
'\\.(mjs|cjs|js)$': [
require.resolve('./jestSwcTransform'),
{
sourceMaps: envOptions.enableSourceMaps || envOptions.nextTests,
sourceMaps: envOptions.enableSourceMaps || !envOptions.oldTests,
jsc: {
parser: {
syntax: 'ecmascript',
@@ -149,7 +141,7 @@ async function getProjectConfig(targetPath, displayName) {
'\\.jsx$': [
require.resolve('./jestSwcTransform'),
{
sourceMaps: envOptions.enableSourceMaps || envOptions.nextTests,
sourceMaps: envOptions.enableSourceMaps || !envOptions.oldTests,
jsc: {
parser: {
syntax: 'ecmascript',
@@ -166,7 +158,7 @@ async function getProjectConfig(targetPath, displayName) {
'\\.ts$': [
require.resolve('./jestSwcTransform'),
{
sourceMaps: envOptions.enableSourceMaps || envOptions.nextTests,
sourceMaps: envOptions.enableSourceMaps || !envOptions.oldTests,
jsc: {
parser: {
syntax: 'typescript',
@@ -177,7 +169,7 @@ async function getProjectConfig(targetPath, displayName) {
'\\.tsx$': [
require.resolve('./jestSwcTransform'),
{
sourceMaps: envOptions.enableSourceMaps || envOptions.nextTests,
sourceMaps: envOptions.enableSourceMaps || !envOptions.oldTests,
jsc: {
parser: {
syntax: 'typescript',
@@ -199,9 +191,9 @@ async function getProjectConfig(targetPath, displayName) {
// A bit more opinionated
testMatch: ['**/*.test.{js,jsx,ts,tsx,mjs,cjs}'],
runtime: envOptions.nextTests
? require.resolve('./jestCachingModuleLoader')
: undefined,
runtime: envOptions.oldTests
? undefined
: require.resolve('./jestCachingModuleLoader'),
transformIgnorePatterns: [`/node_modules/(?:${transformIgnorePattern})/`],
...getRoleConfig(closestPkgJson?.backstage?.role),
@@ -237,15 +229,21 @@ async function getRootConfig() {
const targetPackagePath = path.resolve(targetPath, 'package.json');
const exists = await fs.pathExists(targetPackagePath);
const coverageConfig = {
coverageDirectory: path.resolve(targetPath, 'coverage'),
coverageProvider: envOptions.oldTests ? 'v8' : 'babel',
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx,mjs,cjs}', '!**/*.d.ts'],
};
if (!exists) {
return getProjectConfig(targetPath);
return getProjectConfig(targetPath, coverageConfig);
}
// Check whether the current package is a workspace root or not
const data = await fs.readJson(targetPackagePath);
const workspacePatterns = data.workspaces && data.workspaces.packages;
if (!workspacePatterns) {
return getProjectConfig(targetPath);
return getProjectConfig(targetPath, coverageConfig);
}
// If the target package is a workspace root, we find all packages in the
@@ -269,7 +267,9 @@ async function getRootConfig() {
testScript?.includes('backstage-cli test') ||
testScript?.includes('backstage-cli package test');
if (testScript && isSupportedTestScript) {
return await getProjectConfig(projectPath, packageData.name);
return await getProjectConfig(projectPath, {
displayName: packageData.name,
});
}
return undefined;
@@ -279,6 +279,7 @@ async function getRootConfig() {
return {
rootDir: targetPath,
projects: configs,
...coverageConfig,
};
}
@@ -14,61 +14,11 @@
* limitations under the License.
*/
const fs = require('fs');
const { default: JestRuntime } = require('jest-runtime');
const fileTransformCache = new Map();
const scriptTransformCache = new Map();
let runtimeGeneration = 0;
let isWatchMode;
module.exports = class CachingJestRuntime extends JestRuntime {
// Each Jest run creates a new runtime, including when rerunning tests in
// watch mode. This keeps track of whether we've switched runtime instance.
__runtimeGeneration = runtimeGeneration++;
transformFile(filename, options) {
if (!isWatchMode) {
return super.transformFile(filename, options);
}
const entry = fileTransformCache.get(filename);
if (entry) {
// Only check modification time if it's from a different runtime generation
if (entry.generation === this.__runtimeGeneration) {
return entry.code;
}
// Keep track of the modification time of files so that we can properly
// reprocess them in watch mode.
const { mtimeMs } = fs.statSync(filename);
if (mtimeMs > entry.mtimeMs) {
const code = super.transformFile(filename, options);
fileTransformCache.set(filename, {
code,
mtimeMs,
generation: this.__runtimeGeneration,
});
return code;
}
fileTransformCache.set(filename, {
...entry,
generation: this.__runtimeGeneration,
});
return entry.code;
}
const code = super.transformFile(filename, options);
fileTransformCache.set(filename, {
code,
mtimeMs: fs.statSync(filename).mtimeMs,
generation: this.__runtimeGeneration,
});
return code;
}
// This may or may not be a good idea. Theoretically I don't know why this would impact
// test correctness and flakiness, but it seems like it may introduce flakiness and strange failures.
// It does seem to speed up test execution by a fair amount though.
@@ -84,11 +34,3 @@ module.exports = class CachingJestRuntime extends JestRuntime {
return script;
}
};
// Inject hook into createHasteMap, as it's the only way that we can
// determine (from our scope here) if we're in "watch mode" or not.
const originalCreateHasteMap = JestRuntime.createHasteMap;
JestRuntime.createHasteMap = (config, options = undefined) => {
isWatchMode = options && options.watch;
return originalCreateHasteMap(config, options);
};
@@ -17,7 +17,6 @@
const { createHash } = require('crypto');
const { transform } = require('sucrase');
const sucrasePkg = require('sucrase/package.json');
const sucrasePluginPkg = require('@sucrase/jest-plugin/package.json');
const ESM_REGEX = /\b(?:import|export)\b/;
@@ -70,15 +69,12 @@ function createTransformer(config) {
return { code: source };
};
// TODO: contribute something like this to @sucrase/jest-plugin
const getCacheKey = sourceText => {
return createHash('md5')
.update(sourceText)
.update(Buffer.alloc(1))
.update(sucrasePkg.version)
.update(Buffer.alloc(1))
.update(sucrasePluginPkg.version)
.update(Buffer.alloc(1))
.update(JSON.stringify(config))
.update(Buffer.alloc(1))
.update('1') // increment whenever the transform logic in this file changes
+1 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/cli",
"description": "CLI for developing Backstage plugins and apps",
"version": "0.21.2-next.1",
"version": "0.21.2-next.3",
"publishConfig": {
"access": "public"
},
@@ -46,7 +46,6 @@
"@spotify/eslint-config-base": "^14.0.0",
"@spotify/eslint-config-react": "^14.0.0",
"@spotify/eslint-config-typescript": "^14.0.0",
"@sucrase/jest-plugin": "^2.1.1",
"@sucrase/webpack-loader": "^2.0.0",
"@svgr/plugin-jsx": "6.5.x",
"@svgr/plugin-svgo": "6.5.x",
+3
View File
@@ -60,6 +60,9 @@ export async function serveBundle(options: ServeOptions) {
// Paths with dots should still use the history fallback.
// See https://github.com/facebookincubator/create-react-app/issues/387.
disableDotRule: true,
// The index needs to be rewritten relative to the new public path, including subroutes.
index: `${config.output?.publicPath}index.html`,
},
https:
url.protocol === 'https:'
+7
View File
@@ -1,5 +1,12 @@
# @backstage/codemods
## 0.1.42-next.0
### Patch Changes
- Updated dependencies
- @backstage/cli-common@0.1.11-next.0
## 0.1.41
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/codemods",
"description": "A collection of codemods for Backstage projects",
"version": "0.1.41",
"version": "0.1.42-next.0",
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js"
+10
View File
@@ -1,5 +1,15 @@
# @backstage/config-loader
## 1.1.7-next.2
### Patch Changes
- Updated dependencies
- @backstage/cli-common@0.1.11-next.0
- @backstage/config@1.0.5-next.1
- @backstage/errors@1.1.4-next.1
- @backstage/types@1.0.2-next.1
## 1.1.7-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/config-loader",
"description": "Config loading functionality used by Backstage backend, and CLI",
"version": "1.1.7-next.1",
"version": "1.1.7-next.2",
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
+26
View File
@@ -1,5 +1,31 @@
# @backstage/core-app-api
## 1.2.1-next.3
### Patch Changes
- 6870b43dd1: Fix for the automatic rewriting of base URLs.
- 653d7912ac: Made `WebStorage` notify its subscribers when `localStorage` values change in other tabs/windows
- Updated dependencies
- @backstage/config@1.0.5-next.1
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/types@1.0.2-next.1
- @backstage/version-bridge@1.0.3-next.0
## 1.2.1-next.2
### Patch Changes
- b4b5b02315: Tweak feature flag registration so that it happens immediately before the first rendering of the app, rather than just after.
- 203271b746: Prevent duplicate feature flag components from rendering in the settings when using <FeatureFlagged /> components
- 8015ff1258: Tweaked wording to use inclusive terminology
- 63310e3987: Apps will now rewrite the `app.baseUrl` configuration to match the current `location.origin`. The `backend.baseUrl` will also be rewritten in the same way when the `app.baseUrl` and `backend.baseUrl` have matching origins. This will reduce the need for separate frontend builds for different environments.
- Updated dependencies
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/config@1.0.5-next.1
- @backstage/types@1.0.2-next.1
- @backstage/version-bridge@1.0.3-next.0
## 1.2.1-next.1
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-app-api",
"description": "Core app API used by Backstage apps",
"version": "1.2.1-next.1",
"version": "1.2.1-next.3",
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
@@ -15,7 +15,13 @@
*/
import { WebStorage } from './WebStorage';
import { ErrorApi, StorageApi } from '@backstage/core-plugin-api';
import {
ErrorApi,
StorageApi,
StorageValueSnapshot,
} from '@backstage/core-plugin-api';
import { buckets } from './WebStorage';
import { JsonValue } from '@backstage/types';
describe('WebStorage Storage API', () => {
const mockErrorApi = { post: jest.fn(), error$: jest.fn() };
@@ -30,6 +36,11 @@ describe('WebStorage Storage API', () => {
...args,
});
};
afterEach(() => {
buckets.clear();
});
it('should return undefined for values which are unset', async () => {
const storage = createWebStorage();
@@ -250,4 +261,50 @@ describe('WebStorage Storage API', () => {
snapshot.value.baz.push({ foo: 'buzz' });
}).toThrow(/Cannot add property 1, object is not extensible/);
});
it('should forward storage events accurately', async () => {
const storage = createWebStorage();
const bucket = storage.forBucket('foo');
localStorage.setItem('/foo/bar%2Fbaz', '"x"');
localStorage.setItem('/foo/bar/baz', '"y"');
expect(bucket.snapshot('bar/baz').value).toBe('x');
expect(bucket.forBucket('bar').snapshot('baz').value).toBe('y');
const notifyPromise = new Promise<StorageValueSnapshot<JsonValue>>(
resolve => {
const subscription = bucket.observe$('bar/baz').subscribe({
next: snapshot => {
resolve(snapshot);
subscription.unsubscribe();
},
});
},
);
await expect(
Promise.race([notifyPromise, 'not-yet-resolved']),
).resolves.toBe('not-yet-resolved');
window.dispatchEvent(new StorageEvent('storage', { key: '/foo/bar/baz' }));
localStorage.setItem('/foo/bar%2Fbaz', '"z"');
await expect(
Promise.race([notifyPromise, 'not-yet-resolved']),
).resolves.toBe('not-yet-resolved');
window.dispatchEvent(
new StorageEvent('storage', { key: '/foo/bar%2Fbaz' }),
);
await expect(notifyPromise).resolves.toEqual({
key: 'bar/baz',
presence: 'present',
value: 'z',
});
expect(bucket.snapshot('bar/baz').value).toEqual('z');
});
});
@@ -22,7 +22,7 @@ import {
import { JsonValue, Observable } from '@backstage/types';
import ObservableImpl from 'zen-observable';
const buckets = new Map<string, WebStorage>();
export const buckets = new Map<string, WebStorage>();
/**
* An implementation of the storage API, that uses the browser's local storage.
@@ -35,6 +35,8 @@ export class WebStorage implements StorageApi {
private readonly errorApi: ErrorApi,
) {}
private static hasSubscribed = false;
static create(options: {
errorApi: ErrorApi;
namespace?: string;
@@ -42,6 +44,16 @@ export class WebStorage implements StorageApi {
return new WebStorage(options.namespace ?? '', options.errorApi);
}
private static addStorageEventListener() {
window.addEventListener('storage', event => {
for (const [bucketPath, webStorage] of buckets.entries()) {
if (event.key?.startsWith(bucketPath)) {
webStorage.handleStorageChange(event.key);
}
}
});
}
get<T>(key: string): T | undefined {
return this.snapshot(key).value as T | undefined;
}
@@ -89,9 +101,26 @@ export class WebStorage implements StorageApi {
observe$<T extends JsonValue>(
key: string,
): Observable<StorageValueSnapshot<T>> {
if (!WebStorage.hasSubscribed) {
WebStorage.addStorageEventListener();
WebStorage.hasSubscribed = true;
}
return this.observable.filter(({ key: messageKey }) => messageKey === key);
}
private handleStorageChange(eventKey: StorageEvent['key']) {
if (!eventKey?.startsWith(this.namespace)) {
return;
}
// Grab the part of this key that is local to this bucket
const trimmedKey = eventKey?.slice(`${this.namespace}/`.length);
// If the key still contains a slash, it means it's a sub-bucket
if (!trimmedKey.includes('/')) {
this.notifyChanges(decodeURIComponent(trimmedKey));
}
}
private getKeyName(key: string) {
return `${this.namespace}/${encodeURIComponent(key)}`;
}
@@ -81,7 +81,9 @@ describe.each(['beta', 'stable'])('react-router %s', rrVersion => {
configLoader: async () => [
{
context: 'test',
data: { app: { baseUrl: 'http://localhost/foo' } },
data: {
app: { baseUrl: 'http://localhost/foo' },
},
},
],
bindRoutes: () => {},
@@ -62,7 +62,9 @@ describe('AppManager', () => {
configLoader: async () => [
{
context: 'test',
data: { app: { baseUrl: 'http://localhost/foo' } },
data: {
app: { baseUrl: 'http://localhost/foo' },
},
},
],
});
@@ -94,7 +96,9 @@ describe('AppManager', () => {
configLoader: async () => [
{
context: 'test',
data: { app: { baseUrl: 'http://localhost/foo' } },
data: {
app: { baseUrl: 'http://localhost/foo' },
},
},
],
});
@@ -38,6 +38,7 @@ import {
} from '@backstage/core-plugin-api';
import { AppManager } from './AppManager';
import { AppComponents, AppIcons } from './types';
import { FeatureFlagged } from '../routing/FeatureFlagged';
describe('Integration Test', () => {
const noOpAnalyticsApi = createApiFactory(
@@ -434,6 +435,58 @@ describe('Integration Test', () => {
expect(screen.getByText('Flags: foo')).toBeInTheDocument();
});
it('should prevent duplicate feature flags from being rendered', async () => {
const p1 = createPlugin({
id: 'p1',
featureFlags: [{ name: 'show-p1-feature' }],
});
const p2 = createPlugin({
id: 'p2',
featureFlags: [{ name: 'show-p2-feature' }],
});
const app = new AppManager({
apis: [],
defaultApis: [],
themes,
icons,
plugins: [p1, p2],
components,
configLoader: async () => [],
});
const Provider = app.getProvider();
const Router = app.getRouter();
function FeatureFlags() {
const featureFlags = useApi(featureFlagsApiRef);
return (
<div>{`Flags: ${featureFlags
.getRegisteredFlags()
.map(f => f.name)
.join(',')}`}</div>
);
}
await renderWithEffects(
<Provider>
<Router>
<FeatureFlagged with="show-p1-feature">
<div>My feature behind a flag</div>
</FeatureFlagged>
<FeatureFlagged with="show-p2-feature">
<div>My feature behind a flag</div>
</FeatureFlagged>
<FeatureFlags />
</Router>
</Provider>,
);
expect(
screen.getByText('Flags: show-p1-feature,show-p2-feature'),
).toBeInTheDocument();
});
it('should track route changes via analytics api', async () => {
const mockAnalyticsApi = new MockAnalyticsApi();
const apis = [createApiFactory(analyticsApiRef, mockAnalyticsApi)];
@@ -567,4 +620,107 @@ describe('Integration Test', () => {
),
]);
});
describe('relative url resolvers', () => {
it.each([
[
['http://localhost', 'http://localhost'],
{
backend: {
baseUrl: 'http://localhost:8008',
},
app: {
baseUrl: 'http://localhost:8008',
},
},
],
[
['http://localhost/backstage', 'http://localhost/backstage'],
{
backend: {
baseUrl: 'http://test.com/backstage',
},
app: {
baseUrl: 'http://test.com/backstage',
},
},
],
[
[
'http://localhost/backstage/instance',
'http://localhost/backstage/instance',
],
{
backend: {
baseUrl: 'http://test.com/backstage/instance',
},
app: {
baseUrl: 'http://test.com/backstage/instance',
},
},
],
[
[
'http://localhost/backstage/instance',
'http://test.com/backstage/instance',
],
{
backend: {
baseUrl: 'http://test.com/backstage/instance',
},
app: {
baseUrl: 'http://test-front.com/backstage/instance',
},
},
],
])(
'should be %p when %p',
async ([expectedAppUrl, expectedBackendUrl], data) => {
const app = new AppManager({
apis: [],
defaultApis: [],
themes: [
{
id: 'light',
title: 'Light Theme',
variant: 'light',
Provider: ({ children }) => <>{children}</>,
},
],
icons,
plugins: [],
components,
configLoader: async () => [
{
context: 'test',
data,
},
],
});
const Provider = app.getProvider();
const ConfigDisplay = ({ configString }: { configString: string }) => {
const config = useApi(configApiRef);
return (
<span>
{configString}: {config?.getString(configString)}
</span>
);
};
const dom = await renderWithEffects(
<Provider>
<ConfigDisplay configString="app.baseUrl" />
<ConfigDisplay configString="backend.baseUrl" />
</Provider>,
);
expect(dom.getByText(`app.baseUrl: ${expectedAppUrl}`)).toBeTruthy();
expect(
dom.getByText(`backend.baseUrl: ${expectedBackendUrl}`),
).toBeTruthy();
},
);
});
});
+74 -3
View File
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { Config } from '@backstage/config';
import { AppConfig, Config } from '@backstage/config';
import React, {
ComponentType,
createContext,
@@ -154,7 +154,73 @@ function useConfigLoader(
};
}
const configReader = ConfigReader.fromConfigs(config.value ?? []);
let configReader;
/**
* config.value can be undefined or empty. If it's either, don't bother overriding anything.
*/
if (config.value?.length) {
const urlConfigReader = ConfigReader.fromConfigs(config.value);
/**
* Return the origin of the given URL.
* @param url An absolute URL.
* @returns The given URL's origin.
* @throws If fullUrl is not a correctly formatted absolute URL.
*/
const getOrigin = (url: string) => new URL(url).origin;
/**
* Resolve an absolute URL as relative to the current document.
* @param fullUrl URL to resolve.
* @returns Absolute URL with origin as the current document origin.
* @throws If fullUrl is not a correctly formatted absolute URL.
*/
const overrideOrigin = (fullUrl: string) => {
return new URL(
fullUrl.replace(getOrigin(fullUrl), ''),
document.location.origin,
).href.replace(/\/$/, '');
};
/**
* Test configs may not define `app.baseUrl` or `backend.baseUrl` and we
* don't want to enforce here.
*/
const appBaseUrl = urlConfigReader.getOptionalString('app.baseUrl');
const backendBaseUrl = urlConfigReader.getOptionalString('backend.baseUrl');
let configs = config.value;
const relativeResolverConfig: AppConfig = {
data: {},
context: 'relative-resolver',
};
if (appBaseUrl && backendBaseUrl) {
const appOrigin = getOrigin(appBaseUrl);
const backendOrigin = getOrigin(backendBaseUrl);
if (appOrigin === backendOrigin) {
const newBackendBaseUrl = overrideOrigin(backendBaseUrl);
if (backendBaseUrl !== newBackendBaseUrl) {
relativeResolverConfig.data.backend = { baseUrl: newBackendBaseUrl };
}
}
}
if (appBaseUrl) {
const newAppBaseUrl = overrideOrigin(appBaseUrl);
if (appBaseUrl !== newAppBaseUrl) {
relativeResolverConfig.data.app = { baseUrl: newAppBaseUrl };
}
}
/**
* Only add the relative config if there is actually data to add.
*/
if (Object.keys(relativeResolverConfig.data).length) {
configs = configs.concat([relativeResolverConfig]);
}
configReader = ConfigReader.fromConfigs(configs);
} else {
configReader = ConfigReader.fromConfigs([]);
}
return { api: configReader };
}
@@ -322,8 +388,13 @@ export class AppManager implements BackstageApp {
// Go through the featureFlags returned from the traversal and
// register those now the configApi has been loaded
const registeredFlags = featureFlagsApi.getRegisteredFlags();
const flagNames = new Set(registeredFlags.map(f => f.name));
for (const name of featureFlags) {
featureFlagsApi.registerFlag({ name, pluginId: '' });
// Prevents adding duplicate feature flags
if (!flagNames.has(name)) {
featureFlagsApi.registerFlag({ name, pluginId: '' });
}
}
}
}
+45
View File
@@ -1,5 +1,50 @@
# @backstage/core-components
## 0.12.1-next.3
### Patch Changes
- 91bba69ef8: Internal refactor to remove deprecated symbols.
- Updated dependencies
- @backstage/config@1.0.5-next.1
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/errors@1.1.4-next.1
- @backstage/theme@0.2.16
- @backstage/version-bridge@1.0.3-next.0
## 0.12.1-next.2
### Patch Changes
- d2e3bf6737: Made AlertDisplay not crash on undefined messages
- 5fb6d5e92e: Updated dependency `@react-hookz/web` to `^19.0.0`.
- 146378c146: Updated dependency `@react-hookz/web` to `^20.0.0`.
- 8015ff1258: Tweaked wording to use inclusive terminology
- 830687539f: Sync components in @backstage/core-components with the Component Design Guidelines
- 1ae86ab5fb: Added an option to allow the `AlertMessage` to be self-closing. This is done with a new `display` property that is set to `transient` on the `AlertMessage` when triggering a message to the `AlertApi`. The length of time that these transient messages stay open for can be set using the `transientTimeoutMs` prop on the `AlertDisplay` in the `App.tsx`. Here is an example:
```diff
const App = () => (
<AppProvider>
+ <AlertDisplay transientTimeoutMs={2500} />
<OAuthRequestDialog />
<AppRouter>
<Root>{routes}</Root>
</AppRouter>
</AppProvider>
);
```
The above example will set the transient timeout to 2500ms from the default of 5000ms
- 16e31e690f: InfoCard - Remove subheader container when there is not a subheader or icon
- Updated dependencies
- @backstage/core-plugin-api@1.2.0-next.2
- @backstage/config@1.0.5-next.1
- @backstage/errors@1.1.4-next.1
- @backstage/theme@0.2.16
- @backstage/version-bridge@1.0.3-next.0
## 0.12.1-next.1
### Patch Changes
+2 -1
View File
@@ -55,12 +55,13 @@ import { WithStyles } from '@material-ui/core/styles';
// @public
export function AlertDisplay(props: AlertDisplayProps): JSX.Element | null;
// @public (undocumented)
// @public
export type AlertDisplayProps = {
anchorOrigin?: {
vertical: 'top' | 'bottom';
horizontal: 'left' | 'center' | 'right';
};
transientTimeoutMs?: number;
};
// @public
+2 -2
View File
@@ -1,7 +1,7 @@
{
"name": "@backstage/core-components",
"description": "Core components used by Backstage plugins and apps",
"version": "0.12.1-next.1",
"version": "0.12.1-next.3",
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
@@ -41,7 +41,7 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
"@react-hookz/web": "^19.0.0",
"@react-hookz/web": "^20.0.0",
"@types/react-sparklines": "^1.7.0",
"@types/react-text-truncate": "^0.14.0",
"ansi-regex": "^6.0.1",
@@ -14,13 +14,15 @@
* limitations under the License.
*/
import React from 'react';
import { screen } from '@testing-library/react';
import { AlertDisplay } from './AlertDisplay';
import { alertApiRef } from '@backstage/core-plugin-api';
import { AlertMessage, alertApiRef } from '@backstage/core-plugin-api';
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
import { fireEvent, screen } from '@testing-library/react';
import { AlertApiForwarder } from '@backstage/core-app-api';
import { AlertDisplay } from './AlertDisplay';
import Observable from 'zen-observable';
import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
import React from 'react';
import { act } from '@testing-library/react';
const TEST_MESSAGE = 'TEST_MESSAGE';
@@ -93,4 +95,263 @@ describe('<AlertDisplay />', () => {
expect(screen.getByText('(2 older messages)')).toBeInTheDocument();
});
});
describe('with transient message', () => {
const apis = [
[
alertApiRef,
{
post() {},
alert$() {
return Observable.of<AlertMessage>({
message: 'transient message one',
display: 'transient',
});
},
},
] as const,
] as const;
it('renders message and then removes it', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay />
</TestApiProvider>,
);
expect(queryByText('transient message one')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(5005);
});
expect(queryByText('transient message one')).not.toBeInTheDocument();
jest.useRealTimers();
});
it('respects transientTimeoutMs prop', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay transientTimeoutMs={2500} />
</TestApiProvider>,
);
expect(queryByText('transient message one')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(2505);
});
expect(queryByText('transient message one')).not.toBeInTheDocument();
jest.useRealTimers();
});
});
describe('with multiple transient messages', () => {
const alert$ = () =>
new Observable<AlertMessage>(subscriber => {
subscriber.next({
message: 'transient message one',
display: 'transient',
});
setTimeout(() => {
subscriber.next({
message: 'transient message two',
display: 'transient',
});
}, 1000);
setTimeout(() => {
subscriber.next({
message: 'transient message three',
display: 'transient',
});
}, 2000);
});
const apis = [
[
alertApiRef,
{
post() {},
alert$,
},
] as const,
] as const;
it('renders message and then removes it', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay />
</TestApiProvider>,
);
// Validate adding messages
expect(queryByText('transient message one')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(1000);
});
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(1000);
});
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(2 older messages)')).toBeInTheDocument();
// Validate removing messages
act(() => {
jest.advanceTimersByTime(5000);
});
expect(queryByText('transient message two')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(5000);
});
expect(queryByText('transient message three')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(5000);
});
expect(queryByText('transient message')).not.toBeInTheDocument();
jest.useRealTimers();
});
it('renders 3 different messages with overlapping timeout', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay transientTimeoutMs={1500} />
</TestApiProvider>,
);
// 3 messages stacked with 1.5s each, display times: 0-1.5, 1.5-3, 3-4.5
// 0s in, only message 1
expect(queryByText('transient message one')).toBeInTheDocument();
// 1s in, message 1 still shown, message 2 added in background
act(() => jest.advanceTimersByTime(1000));
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
// 2s in, message 2 now shown, message 3 added
act(() => jest.advanceTimersByTime(1000));
expect(queryByText('transient message two')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
// 3.5s in, message 3 now shown
act(() => jest.advanceTimersByTime(1500));
expect(queryByText('transient message three')).toBeInTheDocument();
// 5s in, all messages gone
act(() => jest.advanceTimersByTime(1500));
expect(queryByText('transient message three')).not.toBeInTheDocument();
jest.useRealTimers();
});
it('renders 3 different messages with overlapping timeout and manual removal', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay transientTimeoutMs={1500} />
</TestApiProvider>,
);
// 3 messages stacked with 1.5s each, display times: 0-1.5, 1.5-3, 3-4.5
// 0s in, only message 1
expect(queryByText('transient message one')).toBeInTheDocument();
// 1s in, message 1 still shown, message 2 added in background
act(() => jest.advanceTimersByTime(1000));
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
// manually remove message 1
fireEvent.click(screen.getByTestId('error-button-close'));
expect(screen.getByText('transient message two')).toBeInTheDocument();
// 2s in, message 2 now shown, message 3 added
act(() => jest.advanceTimersByTime(1000));
expect(queryByText('transient message two')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
// 3s in, message 3 now shown
act(() => jest.advanceTimersByTime(1500));
expect(queryByText('transient message three')).toBeInTheDocument();
// 4s in, all messages gone
act(() => jest.advanceTimersByTime(1500));
expect(queryByText('transient message three')).not.toBeInTheDocument();
jest.useRealTimers();
});
});
describe('with multiple messages of mixed display', () => {
const alert$ = () =>
new Observable<AlertMessage>(subscriber => {
subscriber.next({
message: 'transient message one',
display: 'transient',
});
setTimeout(() => {
subscriber.next({
message: 'permanent message',
display: 'permanent',
});
}, 1000);
setTimeout(() => {
subscriber.next({
message: 'transient message three',
display: 'transient',
});
}, 2000);
});
const apis = [
[
alertApiRef,
{
post() {},
alert$,
},
] as const,
] as const;
it('renders message and then removes it', async () => {
jest.useFakeTimers();
const { queryByText } = await renderInTestApp(
<TestApiProvider apis={apis}>
<AlertDisplay />
</TestApiProvider>,
);
// Validate adding messages
expect(queryByText('transient message one')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(1000);
});
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(1000);
});
expect(queryByText('transient message one')).toBeInTheDocument();
expect(queryByText('(2 older messages)')).toBeInTheDocument();
// Validate removing messages
act(() => {
jest.advanceTimersByTime(5000);
});
expect(queryByText('permanent message')).toBeInTheDocument();
expect(queryByText('(1 older message)')).toBeInTheDocument();
fireEvent.click(screen.getByTestId('error-button-close'));
expect(queryByText('transient message three')).toBeInTheDocument();
act(() => {
jest.advanceTimersByTime(5000);
});
expect(queryByText('transient message')).not.toBeInTheDocument();
jest.useRealTimers();
});
});
});
@@ -22,14 +22,17 @@ import { Alert } from '@material-ui/lab';
import pluralize from 'pluralize';
import React, { useEffect, useState } from 'react';
// TODO: improve on this and promote to a shared component for use by all apps.
/** @public */
/**
* Properties for {@link AlertDisplay}
*
* @public
*/
export type AlertDisplayProps = {
anchorOrigin?: {
vertical: 'top' | 'bottom';
horizontal: 'left' | 'center' | 'right';
};
transientTimeoutMs?: number;
};
/**
@@ -39,12 +42,33 @@ export type AlertDisplayProps = {
* @remarks
*
* Shown as SnackBar at the center top of the page by default. Configurable with props.
*
* @param anchorOrigin - The `vertical` property will set the vertical orientation of where the AlertDisplay will be located
* and the `horizontal` property will set the horizontal orientation of where the AlertDisplay will be located
* @param transientTimeoutMs - Number of milliseconds a transient alert will stay open for. Default value is 5000
*
* @example
* Here's some examples:
* ```
* // This example shows the default usage, the SnackBar will show up at the top in the center and any transient messages will stay open for 5000ms
* <AlertDisplay />
*
* // With this example the SnackBar will show up in the bottom right hand corner and any transient messages will stay open for 2500ms
* <AlertDisplay transientTimeoutMs={2500} anchorOrigin={{vertical: 'bottom', horizontal: 'right'}}/>
*
* // If you want to just set the time a transientTimeoutMs, you can do that like this:
* <AlertDisplay transientTimeoutMs={10000} />
* ```
*/
export function AlertDisplay(props: AlertDisplayProps) {
const [messages, setMessages] = useState<Array<AlertMessage>>([]);
const alertApi = useApi(alertApiRef);
const { anchorOrigin = { vertical: 'top', horizontal: 'center' } } = props;
const {
anchorOrigin = { vertical: 'top', horizontal: 'center' },
transientTimeoutMs,
} = props;
const timeoutMs = transientTimeoutMs ?? 5000;
useEffect(() => {
const subscription = alertApi
@@ -56,12 +80,25 @@ export function AlertDisplay(props: AlertDisplayProps) {
};
}, [alertApi]);
const [firstMessage] = messages;
useEffect(() => {
if (firstMessage && firstMessage.display === 'transient') {
const timeout = setTimeout(() => {
setMessages(msgs => {
const newMsgs = msgs.filter(msg => msg !== firstMessage);
return newMsgs.length === msgs.length ? msgs : newMsgs;
});
}, timeoutMs);
return () => clearTimeout(timeout);
}
return undefined;
}, [firstMessage, timeoutMs]);
if (messages.length === 0) {
return null;
}
const [firstMessage] = messages;
const handleClose = () => {
setMessages(msgs => msgs.filter(msg => msg !== firstMessage));
};
@@ -16,6 +16,7 @@
import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { within } from '@testing-library/react';
import { InfoCard } from './InfoCard';
const minProps = {
@@ -36,4 +37,38 @@ describe('<InfoCard />', () => {
const rendered = await renderInTestApp(<InfoCard {...minProps} />);
expect(rendered.getByText('A deepLink title')).toBeInTheDocument();
});
describe('Subheader', () => {
it('shows the subheader passed in via the subheader prop', async () => {
const { getByTestId } = await renderInTestApp(
<InfoCard {...minProps} subheader="example subheader" />,
);
const subheaderContainer = getByTestId('info-card-subheader');
expect(
within(subheaderContainer).getByText('example subheader'),
).toBeInTheDocument();
});
it('shows the icon passed in via the icon prop', async () => {
const { getByTestId } = await renderInTestApp(
<InfoCard {...minProps} icon={<span data-testid="mock-icon" />} />,
);
const subheaderContainer = getByTestId('info-card-subheader');
expect(
within(subheaderContainer).getByTestId('mock-icon'),
).toBeInTheDocument();
});
it('is not rendered where there is not an icon or subheading', async () => {
const { queryByTestId } = await renderInTestApp(
<InfoCard {...minProps} />,
);
expect(queryByTestId('info-card-subheader')).not.toBeInTheDocument();
});
});
});

Some files were not shown because too many files have changed in this diff Show More