diff --git a/.changeset/beige-carpets-double.md b/.changeset/beige-carpets-double.md
new file mode 100644
index 0000000000..98e0d8d69a
--- /dev/null
+++ b/.changeset/beige-carpets-double.md
@@ -0,0 +1,9 @@
+---
+'@backstage/plugin-code-coverage': minor
+---
+
+Cleaned up API exports.
+
+The `Router` export has been removed; users are expected to use `EntityCodeCoverageContent` instead.
+
+The `isPluginApplicableToEntity` helper has been deprecated, in favor of the `isCodeCoverageAvailable` helper.
diff --git a/.changeset/beige-carpets-triple.md b/.changeset/beige-carpets-triple.md
new file mode 100644
index 0000000000..5eda26fb02
--- /dev/null
+++ b/.changeset/beige-carpets-triple.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-code-coverage-backend': minor
+---
+
+Cleaned up API exports.
+
+The `CodeCoverageApi` and `makeRouter` exports have been removed from the backend, since they were not meant to be exported in the first place.
diff --git a/.changeset/cuddly-flowers-provide.md b/.changeset/cuddly-flowers-provide.md
new file mode 100644
index 0000000000..729ac96cda
--- /dev/null
+++ b/.changeset/cuddly-flowers-provide.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-fossa': patch
+---
+
+Allow configuration of base URL for Fossa links
diff --git a/.changeset/fifty-vans-drum.md b/.changeset/fifty-vans-drum.md
new file mode 100644
index 0000000000..6b1b920bb9
--- /dev/null
+++ b/.changeset/fifty-vans-drum.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-tech-radar': patch
+---
+
+Update tech-radar documentation on how to use an external json data source with dates.
diff --git a/.changeset/little-geckos-end.md b/.changeset/little-geckos-end.md
new file mode 100644
index 0000000000..328095aa44
--- /dev/null
+++ b/.changeset/little-geckos-end.md
@@ -0,0 +1,18 @@
+---
+'@backstage/plugin-kubernetes-backend': minor
+---
+
+Add new endpoints to Kubernetes backend plugin
+
+BREAKING: Kubernetes backend plugin now depends on CatalogApi
+
+```typescript
+// Create new CatalogClient
+const catalogApi = new CatalogClient({ discoveryApi: env.discovery });
+const { router } = await KubernetesBuilder.createBuilder({
+ logger: env.logger,
+ config: env.config,
+ // Inject it into createBuilder params
+ catalogApi,
+}).build();
+```
diff --git a/.changeset/pink-cars-pretend.md b/.changeset/pink-cars-pretend.md
new file mode 100644
index 0000000000..c46cb99f55
--- /dev/null
+++ b/.changeset/pink-cars-pretend.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+new setUserAsOwner flag for publish:gitlab action
+
+The field default is `false`. When true it will use the token configured in the gitlab integration for the matching host, to try and set the user logged in via `repoUrlPicker` `requestUserCredentials` OAuth flow as owner of the repository created in GitLab.
diff --git a/.changeset/renovate-4338117.md b/.changeset/renovate-4338117.md
new file mode 100644
index 0000000000..199073c599
--- /dev/null
+++ b/.changeset/renovate-4338117.md
@@ -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 `^15.0.0`.
diff --git a/.changeset/renovate-913f3dc.md b/.changeset/renovate-913f3dc.md
new file mode 100644
index 0000000000..edb2f95356
--- /dev/null
+++ b/.changeset/renovate-913f3dc.md
@@ -0,0 +1,5 @@
+---
+'@backstage/config-loader': patch
+---
+
+Updated dependency `typescript-json-schema` to `^0.54.0`.
diff --git a/.changeset/renovate-dd35ce8.md b/.changeset/renovate-dd35ce8.md
new file mode 100644
index 0000000000..9d828bc42d
--- /dev/null
+++ b/.changeset/renovate-dd35ce8.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-kubernetes-backend': patch
+'@backstage/plugin-kubernetes-common': patch
+'@backstage/plugin-kubernetes': patch
+---
+
+Updated dependency `@kubernetes/client-node` to `^0.17.0`.
diff --git a/.changeset/ten-cobras-wash.md b/.changeset/ten-cobras-wash.md
new file mode 100644
index 0000000000..81915d958d
--- /dev/null
+++ b/.changeset/ten-cobras-wash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend': minor
+---
+
+Allowed post method on /refresh path
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e38df375b6..06f89b06d3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,7 +32,7 @@ jobs:
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
@@ -61,7 +61,7 @@ jobs:
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
@@ -178,7 +178,7 @@ jobs:
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml
index 5b5c8b63c8..228d4c62ac 100644
--- a/.github/workflows/cron.yml
+++ b/.github/workflows/cron.yml
@@ -8,7 +8,7 @@ jobs:
cron:
runs-on: ubuntu-latest
steps:
- - uses: backstage/actions/cron@v0.5.0
+ - uses: backstage/actions/cron@v0.5.2
with:
app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }}
private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }}
diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml
index 6cb97d1a9e..93d59b64bd 100644
--- a/.github/workflows/deploy_docker-image.yml
+++ b/.github/workflows/deploy_docker-image.yml
@@ -69,17 +69,17 @@ jobs:
working-directory: ./example-app
- name: Login to GitHub Container Registry
- uses: docker/login-action@v1
+ uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
+ uses: docker/setup-buildx-action@v2
- name: Build and push
- uses: docker/build-push-action@v2
+ uses: docker/build-push-action@v3
with:
context: './example-app'
file: ./example-app/packages/backend/Dockerfile
diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml
index 427a7139a0..719b5ea94b 100644
--- a/.github/workflows/deploy_nightly.yml
+++ b/.github/workflows/deploy_nightly.yml
@@ -26,7 +26,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml
index 30d4bf9ee2..371712fedb 100644
--- a/.github/workflows/deploy_packages.yml
+++ b/.github/workflows/deploy_packages.yml
@@ -67,7 +67,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
@@ -145,7 +145,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml
index bc0dd15617..de02e45e76 100644
--- a/.github/workflows/issue.yaml
+++ b/.github/workflows/issue.yaml
@@ -10,4 +10,4 @@ jobs:
if: github.repository == 'backstage/backstage'
steps:
- name: Issue sync
- uses: backstage/actions/issue-sync@v0.5.0
+ uses: backstage/actions/issue-sync@v0.5.2
diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml
new file mode 100644
index 0000000000..25475a03dc
--- /dev/null
+++ b/.github/workflows/pr-review-comment-trigger.yaml
@@ -0,0 +1,19 @@
+# This workflow is used to trigger the "PR Review Comment" workflow. This chaining is needed
+# because workflows triggered by pull_request_review_comment do not have access to secrets.
+
+name: PR Review Comment Trigger
+on:
+ pull_request_review_comment:
+ types:
+ - created
+
+jobs:
+ trigger:
+ runs-on: ubuntu-latest
+
+ # The "PR Review Comment" workflow will check the success status of this workflow and only mark
+ # the PR for re-review if this workflow was successful, which is when the author leaves a review comment.
+ if: github.repository == 'backstage/backstage' && github.event.comment.user.id == github.event.pull_request.user.id
+
+ steps:
+ - run: echo "This PR needs another review"
diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml
new file mode 100644
index 0000000000..65252bae09
--- /dev/null
+++ b/.github/workflows/pr-review-comment.yaml
@@ -0,0 +1,24 @@
+# This workflow is triggered by "PR Review Comment Trigger"
+
+name: PR Review Comment
+on:
+ workflow_run:
+ workflows: [PR Review Comment Trigger]
+ types:
+ - completed
+
+jobs:
+ re-review:
+ runs-on: ubuntu-latest
+
+ # The triggering workflow will report success if the PR needs re-review
+ if: github.repository == 'backstage/backstage' && github.event.workflow_run.conclusion == 'success'
+
+ steps:
+ - uses: backstage/actions/re-review@v0.5.2
+ with:
+ app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }}
+ private-key: ${{ secrets.BACKSTAGE_GOALIE_PRIVATE_KEY }}
+ installation-id: ${{ secrets.BACKSTAGE_GOALIE_INSTALLATION_ID }}
+ project-id: PVT_kwDOBFKqdc02LQ
+ issue-number: ${{ github.event.workflow_run.pull_requests[0].number }}
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index c8fe3e2d69..e5945f6f20 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -9,9 +9,6 @@ on:
issue_comment:
types:
- created
- pull_request_review_comment:
- types:
- - created
jobs:
sync:
@@ -21,7 +18,7 @@ jobs:
if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request )
steps:
- name: PR sync
- uses: backstage/actions/pr-sync@v0.5.0
+ uses: backstage/actions/pr-sync@v0.5.2
with:
github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }}
app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }}
diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml
index 0d3add5f12..b04a0a3de0 100644
--- a/.github/workflows/sync_code-formatting.yml
+++ b/.github/workflows/sync_code-formatting.yml
@@ -20,7 +20,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml
index 9d0726e915..d2af1307b0 100644
--- a/.github/workflows/sync_snyk-github-issues.yml
+++ b/.github/workflows/sync_snyk-github-issues.yml
@@ -22,7 +22,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml
index 126670b67f..811372d54d 100644
--- a/.github/workflows/verify_e2e-linux.yml
+++ b/.github/workflows/verify_e2e-linux.yml
@@ -46,7 +46,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml
index 89679b530a..1aea51bec9 100644
--- a/.github/workflows/verify_storybook.yml
+++ b/.github/workflows/verify_storybook.yml
@@ -35,7 +35,7 @@ jobs:
node-version: ${{ matrix.node-version }}
registry-url: https://registry.npmjs.org/ # Needed for auth
- name: yarn install
- uses: backstage/actions/yarn-install@v0.5.0
+ uses: backstage/actions/yarn-install@v0.5.2
with:
cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }}
- name: storybook yarn install
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 1cb0577c44..6bf1f482bf 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -23,7 +23,7 @@ _You can do this by using the [Adopter form](https://form.typeform.com/to/zcOaKi
| [Fiverr](https://www.fiverr.com) | [@nirga](https://github.com/nirga) | Unifying separate tools that developers are using today (i.e. monitoring, dead letter queues management, etc.) into a single platform. |
| [Zalando SE](https://www.zalando.de) | [@leviferreira](https://github.com/leviferreira) | Building V2 of the Internal Development Portal. |
| [LegalZoom](https://legalzoom.com) | [@backjo](https://github.com/backjo) | Developer portal - hub for all engineering projects and metadata. |
-| [Expedia Group](https://www.expediagroup.com) | [@guillermomanzo](https://github.com/guillermomanzo), [Sheena Sharma](mailto:shesharma@expediagroup.com) | EG Common Developer Toolkit |
+| [Expedia Group](https://www.expediagroup.com) | [@guillermomanzo](https://github.com/guillermomanzo), [Sheena Sharma](mailto:shesharma@expediagroup.com), [@ajbw](https://github.com/ajbw) | EG Common Developer Toolkit |
| [Paddle.com](https://paddle.com) | [Ioannis Georgoulas](https://github.com/geototti21) | Developer portal (Tech Docs, Service Catalog, Internal Tooling), we use vanilla Backstage FE and custom BE implementation in Go |
| [Acast.com](https://acast.com) | [Olle Lundberg](https://github.com/lndbrg) | Developer portal with tech docs, service catalog and a bunch of other internal tooling |
| [Lunar](https://lunar.app) | [Jacob Valdemar](https://github.com/JacobValdemar) | Internal developer portal for service overview and insights, API documentation, technical guides, onboarding guides and RFC's. |
@@ -188,5 +188,5 @@ _You can do this by using the [Adopter form](https://form.typeform.com/to/zcOaKi
| [Cho Tot](https://www.chotot.com) | [Chotot Team](mailto:sre@chotot.vn) | Internal developer portal, service catalog with CI/CD tools. |
| [William Hill](https://www.williamhillgroup.com/) | [Pat Mills](mailto:pat.mills@williamhill.com), [Nathan Flynn](mailto:nflynn@williamhill.co.uk), and [Nishkarsh Raj](mailto:nishkarsh.raj@williamhill.co.uk) | William Hill are leveraging Backstage to build our Engineering Portal. Our mission is to centralize the software catalog inventory to enable service discoverability, reduce the onboarding time for new Engineers, provide a single pane of glass to accelerate Developer Productivity and Save Engineers time. Our aspiration is to create an InnerSource community focussed on organization-wide patterns that are re-usable and can be self-served with the Scaffolder. |
| [Vodafone NewZealand Limited](https://vodafone.co.nz) | [Ankit Gupta](mailto:ankit.gupta@vodafone.nz), [DevOps COE](mailto:devopstooling@vodafone.nz) | Vodafone NZ are leveraging Backstage to build centralised and self service Engineering Portal. Our mission is to standardised Pipeline templates across the Engineering teams, One shop stop to create the pipelines and repository with a template approach which reduces creation part from days to minutes and no wait time for developers. A unified view for Azure DevOps pipeline, Azure Repo pull requests, Deployment status from Azure RedHat Openshift-ArgoCD and SonarQube Security and code quality scans report on a single pan to provide a streamlined view for all microservices across the app stack. |
-| [Coamo](http://www.coamo.com.br) | [@holiiveira](https://github.com/holiiveira), [@gpxlnx](https://github.com/gpxlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place.
+| [Coamo](http://www.coamo.com.br) | [@holiiveira](https://github.com/holiiveira), [@gpxlnx](https://github.com/gpxlnx) | We're starting to use it as the main tool of a DevOps platform. Our goal is to provide software templates, centralize our software catalog enabling efficient service discovery, and make it easy to manage the entire software ecosystem in one place.
|
diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md
index eb8973bec1..01c18f04cd 100644
--- a/docs/auth/add-auth-provider.md
+++ b/docs/auth/add-auth-provider.md
@@ -350,6 +350,7 @@ router.get('/auth/providerA/handler/frame');
router.post('/auth/providerA/handler/frame');
router.post('/auth/providerA/logout');
router.get('/auth/providerA/refresh'); // if supported
+router.post('/auth/providerA/refresh'); // if supported
```
As you can see each endpoint is prefixed with both `/auth` and its provider
diff --git a/docs/integrations/github/github-apps.md b/docs/integrations/github/github-apps.md
index 5725e67c7b..4f2c58bbec 100644
--- a/docs/integrations/github/github-apps.md
+++ b/docs/integrations/github/github-apps.md
@@ -79,7 +79,7 @@ privateKey: |
### Including in Integrations Config
Once the credentials are stored in a YAML file generated by `create-github-app`,
-or manually by following the [GitHub Enterprise](#gitHub-enterprise)
+or manually by following the [GitHub Enterprise](#github-enterprise)
instructions, they can be included in the `app-config.yaml` under the
`integrations` section.
diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md
index 382399e603..3c9417268b 100644
--- a/docs/overview/architecture-overview.md
+++ b/docs/overview/architecture-overview.md
@@ -341,7 +341,8 @@ separate Docker images.
The backend container can be built by running the following command:
```bash
-yarn run docker-build
+yarn run build
+yarn run build-image
```
This will create a container called `example-backend`.
diff --git a/microsite/data/on-demand/20211117-01.yaml b/microsite/data/on-demand/20211117-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20211117-01.yaml
rename to microsite/data/on-demand/20211117-1.yaml
diff --git a/microsite/data/on-demand/20211118-01.yaml b/microsite/data/on-demand/20211118-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20211118-01.yaml
rename to microsite/data/on-demand/20211118-1.yaml
diff --git a/microsite/data/on-demand/20211215-01.yaml b/microsite/data/on-demand/20211215-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20211215-01.yaml
rename to microsite/data/on-demand/20211215-1.yaml
diff --git a/microsite/data/on-demand/20211216-01.yaml b/microsite/data/on-demand/20211216-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20211216-01.yaml
rename to microsite/data/on-demand/20211216-1.yaml
diff --git a/microsite/data/on-demand/20220216-01.yaml b/microsite/data/on-demand/20220216-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20220216-01.yaml
rename to microsite/data/on-demand/20220216-1.yaml
diff --git a/microsite/data/on-demand/20220223-01.yaml b/microsite/data/on-demand/20220223-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20220223-01.yaml
rename to microsite/data/on-demand/20220223-1.yaml
diff --git a/microsite/data/on-demand/20220518-01.yaml b/microsite/data/on-demand/20220518-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20220518-01.yaml
rename to microsite/data/on-demand/20220518-1.yaml
diff --git a/microsite/data/on-demand/20220525.yaml b/microsite/data/on-demand/20220525-1.yaml
similarity index 100%
rename from microsite/data/on-demand/20220525.yaml
rename to microsite/data/on-demand/20220525-1.yaml
diff --git a/microsite/data/on-demand/20220615-01.yaml b/microsite/data/on-demand/20220615-1.yaml
similarity index 97%
rename from microsite/data/on-demand/20220615-01.yaml
rename to microsite/data/on-demand/20220615-1.yaml
index 8ac660a71c..fb296dd6ce 100644
--- a/microsite/data/on-demand/20220615-01.yaml
+++ b/microsite/data/on-demand/20220615-1.yaml
@@ -1,7 +1,7 @@
---
title: Adopters Community Sessions
date: June 15, 2022
-category: Upcoming
+category: Meetup
description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc.
youtubeUrl: https://youtu.be/aKZnjnE5Wy8
youtubeImgUrl: https://backstage.io/img/b-sessions.png
diff --git a/microsite/data/on-demand/20220622-1.yaml b/microsite/data/on-demand/20220622-1.yaml
index 0bbd53525a..27634609cb 100644
--- a/microsite/data/on-demand/20220622-1.yaml
+++ b/microsite/data/on-demand/20220622-1.yaml
@@ -1,9 +1,9 @@
---
title: Contributor Community Sessions
date: June 22, 2022
-category: Upcoming
+category: Meetup
description: Join the maintainers and contributors for the Contributor Community Sessions
-youtubeUrl: https://youtu.be/aKZnjnE5Wy8
+youtubeUrl: https://youtu.be/E-jWqWXBxUY
youtubeImgUrl: https://backstage.io/img/b-sessions.png
rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com
eventUrl: https://github.com/backstage/community/issues/49
diff --git a/microsite/data/on-demand/20220720-1.yaml b/microsite/data/on-demand/20220720-1.yaml
new file mode 100644
index 0000000000..a1f51859f4
--- /dev/null
+++ b/microsite/data/on-demand/20220720-1.yaml
@@ -0,0 +1,9 @@
+---
+title: Adopters Community Sessions
+date: July 20, 2022
+category: Upcoming
+description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc.
+youtubeUrl: https://youtu.be/4VFNlPxWcx8
+youtubeImgUrl: https://backstage.io/img/b-sessions.png
+rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com
+eventUrl: https://github.com/backstage/community/issues/52
diff --git a/microsite/data/on-demand/20220727-1.yaml b/microsite/data/on-demand/20220727-1.yaml
new file mode 100644
index 0000000000..5f7712596f
--- /dev/null
+++ b/microsite/data/on-demand/20220727-1.yaml
@@ -0,0 +1,9 @@
+---
+title: Contributor Community Sessions
+date: July 27, 2022
+category: Upcoming
+description: Join the maintainers and contributors for the Contributor Community Sessions
+youtubeUrl: https://youtu.be/4VFNlPxWcx8
+youtubeImgUrl: https://backstage.io/img/b-sessions.png
+rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com
+eventUrl: https://github.com/backstage/community/issues/52
diff --git a/microsite/pages/en/live.js b/microsite/pages/en/live.js
index 062af419fc..f2ebd4bb1d 100644
--- a/microsite/pages/en/live.js
+++ b/microsite/pages/en/live.js
@@ -34,7 +34,7 @@ const Background = props => {
diff --git a/packages/backend/src/plugins/kubernetes.ts b/packages/backend/src/plugins/kubernetes.ts
index 8023d549ff..3bc7a5dcbe 100644
--- a/packages/backend/src/plugins/kubernetes.ts
+++ b/packages/backend/src/plugins/kubernetes.ts
@@ -17,13 +17,16 @@
import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';
+import { CatalogClient } from '@backstage/catalog-client';
export default async function createPlugin(
env: PluginEnvironment,
): Promise {
+ const catalogApi = new CatalogClient({ discoveryApi: env.discovery });
const { router } = await KubernetesBuilder.createBuilder({
logger: env.logger,
config: env.config,
+ catalogApi,
}).build();
return router;
}
diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json
index 894e86ef27..3ca4b1455f 100644
--- a/packages/config-loader/package.json
+++ b/packages/config-loader/package.json
@@ -46,7 +46,7 @@
"json-schema-merge-allof": "^0.8.1",
"json-schema-traverse": "^1.0.0",
"node-fetch": "^2.6.7",
- "typescript-json-schema": "^0.53.0",
+ "typescript-json-schema": "^0.54.0",
"yaml": "^1.9.2",
"yup": "^0.32.9"
},
diff --git a/packages/core-components/package.json b/packages/core-components/package.json
index 0d27c6419d..a6dff88333 100644
--- a/packages/core-components/package.json
+++ b/packages/core-components/package.json
@@ -66,7 +66,7 @@
"react-syntax-highlighter": "^15.4.5",
"react-text-truncate": "^0.19.0",
"react-use": "^17.3.2",
- "@react-hookz/web": "^14.0.0",
+ "@react-hookz/web": "^15.0.0",
"react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.6",
"remark-gfm": "^3.0.1",
diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts
index 2232eeaa81..e4fa5eeea4 100644
--- a/plugins/auth-backend/src/service/router.ts
+++ b/plugins/auth-backend/src/service/router.ts
@@ -140,6 +140,7 @@ export async function createRouter(
}
if (provider.refresh) {
r.get('/refresh', provider.refresh.bind(provider));
+ r.post('/refresh', provider.refresh.bind(provider));
}
router.use(`/${providerId}`, r);
diff --git a/plugins/code-coverage-backend/api-report.md b/plugins/code-coverage-backend/api-report.md
index 437c48227f..c33874064b 100644
--- a/plugins/code-coverage-backend/api-report.md
+++ b/plugins/code-coverage-backend/api-report.md
@@ -10,27 +10,10 @@ import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { UrlReader } from '@backstage/backend-common';
-// Warning: (ae-missing-release-tag) "CodeCoverageApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export interface CodeCoverageApi {
- // (undocumented)
- name: string;
-}
-
-// Warning: (ae-missing-release-tag) "createRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function createRouter(options: RouterOptions): Promise;
-// Warning: (ae-missing-release-tag) "makeRouter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const makeRouter: (options: RouterOptions) => Promise;
-
-// Warning: (ae-missing-release-tag) "RouterOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export interface RouterOptions {
// (undocumented)
config: Config;
diff --git a/plugins/code-coverage-backend/src/index.ts b/plugins/code-coverage-backend/src/index.ts
index 3b1b536ac7..8511c9b71e 100644
--- a/plugins/code-coverage-backend/src/index.ts
+++ b/plugins/code-coverage-backend/src/index.ts
@@ -20,4 +20,5 @@
* @packageDocumentation
*/
-export * from './service/router';
+export { createRouter } from './service/router';
+export type { RouterOptions } from './service/router';
diff --git a/plugins/code-coverage-backend/src/service/router.ts b/plugins/code-coverage-backend/src/service/router.ts
index 488103c835..37279b549f 100644
--- a/plugins/code-coverage-backend/src/service/router.ts
+++ b/plugins/code-coverage-backend/src/service/router.ts
@@ -35,6 +35,11 @@ import { Jacoco } from './converter/jacoco';
import { Converter } from './converter';
import { getEntitySourceLocation } from '@backstage/catalog-model';
+/**
+ * Options for {@link createRouter}.
+ *
+ * @public
+ */
export interface RouterOptions {
config: Config;
discovery: PluginEndpointDiscovery;
@@ -211,6 +216,11 @@ export const makeRouter = async (
return router;
};
+/**
+ * Creates a code-coverage plugin backend router.
+ *
+ * @public
+ */
export async function createRouter(
options: RouterOptions,
): Promise {
diff --git a/plugins/code-coverage/api-report.md b/plugins/code-coverage/api-report.md
index 0e675dec04..152cc93103 100644
--- a/plugins/code-coverage/api-report.md
+++ b/plugins/code-coverage/api-report.md
@@ -9,8 +9,6 @@ import { BackstagePlugin } from '@backstage/core-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { RouteRef } from '@backstage/core-plugin-api';
-// Warning: (ae-missing-release-tag) "codeCoveragePlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export const codeCoveragePlugin: BackstagePlugin<
{
@@ -19,20 +17,12 @@ export const codeCoveragePlugin: BackstagePlugin<
{}
>;
-// Warning: (ae-missing-release-tag) "EntityCodeCoverageContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export const EntityCodeCoverageContent: () => JSX.Element;
-// Warning: (ae-missing-release-tag) "isCodeCoverageAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-const isCodeCoverageAvailable: (entity: Entity) => boolean;
-export { isCodeCoverageAvailable };
-export { isCodeCoverageAvailable as isPluginApplicableToEntity };
+// @public
+export function isCodeCoverageAvailable(entity: Entity): boolean;
-// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const Router: () => JSX.Element;
+// @public @deprecated (undocumented)
+export const isPluginApplicableToEntity: typeof isCodeCoverageAvailable;
```
diff --git a/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts
index 225ca96175..d97d147da3 100644
--- a/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts
+++ b/plugins/code-coverage/src/components/FileExplorer/Highlighter.ts
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import 'highlight.js/styles/atom-one-dark.css';
import highlight from 'highlight.js';
diff --git a/plugins/code-coverage/src/components/Router.tsx b/plugins/code-coverage/src/components/Router.tsx
index d3342b86eb..190b441c7a 100644
--- a/plugins/code-coverage/src/components/Router.tsx
+++ b/plugins/code-coverage/src/components/Router.tsx
@@ -13,16 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import React from 'react';
import { Entity } from '@backstage/catalog-model';
import { useEntity } from '@backstage/plugin-catalog-react';
import { CodeCoveragePage } from './CodeCoveragePage';
import { MissingAnnotationEmptyState } from '@backstage/core-components';
-export const isCodeCoverageAvailable = (entity: Entity) =>
- Boolean(entity.metadata.annotations?.['backstage.io/code-coverage']);
+/**
+ * Returns true if the given entity has code coverage enabled.
+ *
+ * @public
+ */
+export function isCodeCoverageAvailable(entity: Entity) {
+ return Boolean(entity.metadata.annotations?.['backstage.io/code-coverage']);
+}
-export const Router = () => {
+/**
+ * @public
+ */
+export const Router = (): JSX.Element => {
const { entity } = useEntity();
if (!isCodeCoverageAvailable(entity)) {
@@ -30,5 +40,6 @@ export const Router = () => {
);
}
+
return ;
};
diff --git a/plugins/code-coverage/src/index.ts b/plugins/code-coverage/src/index.ts
index 2ece7ed1e8..06c10026ff 100644
--- a/plugins/code-coverage/src/index.ts
+++ b/plugins/code-coverage/src/index.ts
@@ -20,9 +20,13 @@
* @packageDocumentation
*/
+import { isCodeCoverageAvailable } from './components/Router';
+
export { codeCoveragePlugin, EntityCodeCoverageContent } from './plugin';
-export {
- Router,
- isCodeCoverageAvailable,
- isCodeCoverageAvailable as isPluginApplicableToEntity,
-} from './components/Router';
+export { isCodeCoverageAvailable };
+
+/**
+ * @public
+ * @deprecated Use `isPluginApplicableToEntity` instead.
+ */
+export const isPluginApplicableToEntity = isCodeCoverageAvailable;
diff --git a/plugins/code-coverage/src/plugin.ts b/plugins/code-coverage/src/plugin.ts
index 1202c4e4b3..f137e9d488 100644
--- a/plugins/code-coverage/src/plugin.ts
+++ b/plugins/code-coverage/src/plugin.ts
@@ -23,6 +23,9 @@ import {
discoveryApiRef,
} from '@backstage/core-plugin-api';
+/**
+ * @public
+ */
export const codeCoveragePlugin = createPlugin({
id: 'code-coverage',
routes: {
@@ -37,6 +40,11 @@ export const codeCoveragePlugin = createPlugin({
],
});
+/**
+ * An entity code coverage page.
+ *
+ * @public
+ */
export const EntityCodeCoverageContent = codeCoveragePlugin.provide(
createRoutableExtension({
name: 'EntityCodeCoverageContent',
diff --git a/plugins/fossa/README.md b/plugins/fossa/README.md
index 898c9d0475..10ccba5ba7 100644
--- a/plugins/fossa/README.md
+++ b/plugins/fossa/README.md
@@ -43,9 +43,12 @@ proxy:
headers:
Authorization: token ${FOSSA_API_TOKEN}
-# if you have a fossa organization, configure your id here
fossa:
+ # if you have a fossa organization, configure your id here
organizationId:
+ # if you have a self-managed fossa instance,
+ # configure the baseUrl to use for links to the fossa page here
+ externalLinkBaseUrl:
```
4. Get an api-token and provide `FOSSA_AUTH_HEADER` as env variable (https://app.fossa.com/account/settings/integrations/api_tokens)
diff --git a/plugins/fossa/config.d.ts b/plugins/fossa/config.d.ts
index 72d844c4e9..26a2823097 100644
--- a/plugins/fossa/config.d.ts
+++ b/plugins/fossa/config.d.ts
@@ -20,6 +20,12 @@ export interface Config {
* The organization id in fossa.
* @visibility frontend
*/
- organizationId: string;
+ organizationId?: string;
+
+ /**
+ * The base url to use for external links (from Backstage to Fossa).
+ * @visibility frontend
+ */
+ externalLinkBaseUrl?: string;
};
}
diff --git a/plugins/fossa/src/api/FossaClient.test.ts b/plugins/fossa/src/api/FossaClient.test.ts
index 65b0fc1d53..0e2dc81e1f 100644
--- a/plugins/fossa/src/api/FossaClient.test.ts
+++ b/plugins/fossa/src/api/FossaClient.test.ts
@@ -175,6 +175,58 @@ describe('FossaClient', () => {
expect(summary).toBeUndefined();
});
+ it('should allow custom external link base url', async () => {
+ client = new FossaClient({
+ discoveryApi,
+ identityApi,
+ organizationId: '8736',
+ externalLinkBaseUrl: 'https://custom.fossa.com', // overrides the default app.fossa.com
+ });
+ server.use(
+ rest.get(`${mockBaseUrl}/fossa/projects`, (req, res, ctx) => {
+ const expectedQuery =
+ 'count=1000&page=0&sort=title%2B&organizationId=8736&title=our-service';
+ if (req.url.searchParams.toString() !== expectedQuery) {
+ return res(
+ ctx.status(500),
+ ctx.body(
+ `${req.url.searchParams.toString()} !== ${expectedQuery}`,
+ ),
+ );
+ }
+
+ return res(
+ ctx.json([
+ {
+ locator: 'custom+8736/our-service',
+ title: 'our-service',
+ default_branch: 'develop',
+ revisions: [
+ {
+ updatedAt: '2020-01-01T00:00:00Z',
+ dependency_count: 160,
+ unresolved_licensing_issue_count: 5,
+ unresolved_issue_count: 100,
+ },
+ ],
+ },
+ ]),
+ );
+ }),
+ );
+
+ const summary = await client.getFindingSummary('our-service');
+
+ expect(summary).toEqual({
+ timestamp: '2020-01-01T00:00:00Z',
+ issueCount: 5,
+ dependencyCount: 160,
+ projectDefaultBranch: 'develop',
+ projectUrl:
+ 'https://custom.fossa.com/projects/custom%2B8736%2Four-service',
+ } as FindingSummary);
+ });
+
it('should handle 404 status', async () => {
server.use(
rest.get(`${mockBaseUrl}/fossa/projects`, (_req, res, ctx) => {
diff --git a/plugins/fossa/src/api/FossaClient.ts b/plugins/fossa/src/api/FossaClient.ts
index 66b44de21e..8b4b4b02e5 100644
--- a/plugins/fossa/src/api/FossaClient.ts
+++ b/plugins/fossa/src/api/FossaClient.ts
@@ -36,20 +36,24 @@ export class FossaClient implements FossaApi {
discoveryApi: DiscoveryApi;
identityApi: IdentityApi;
organizationId?: string;
+ externalLinkBaseUrl: string;
private readonly limit = pLimit(5);
constructor({
discoveryApi,
identityApi,
organizationId,
+ externalLinkBaseUrl = 'https://app.fossa.com',
}: {
discoveryApi: DiscoveryApi;
identityApi: IdentityApi;
organizationId?: string;
+ externalLinkBaseUrl?: string;
}) {
this.discoveryApi = discoveryApi;
this.identityApi = identityApi;
this.organizationId = organizationId;
+ this.externalLinkBaseUrl = externalLinkBaseUrl;
}
private async callApi(
@@ -104,9 +108,9 @@ export class FossaClient implements FossaApi {
revision.unresolved_issue_count,
dependencyCount: revision.dependency_count,
projectDefaultBranch: project.default_branch,
- projectUrl: `https://app.fossa.com/projects/${encodeURIComponent(
- project.locator,
- )}`,
+ projectUrl: `${
+ this.externalLinkBaseUrl
+ }/projects/${encodeURIComponent(project.locator)}`,
},
};
}
diff --git a/plugins/fossa/src/plugin.ts b/plugins/fossa/src/plugin.ts
index a586d6d8a6..954ecedc81 100644
--- a/plugins/fossa/src/plugin.ts
+++ b/plugins/fossa/src/plugin.ts
@@ -39,6 +39,9 @@ export const fossaPlugin = createPlugin({
discoveryApi,
identityApi,
organizationId: configApi.getOptionalString('fossa.organizationId'),
+ externalLinkBaseUrl: configApi.getOptionalString(
+ 'fossa.externalLinkBaseUrl',
+ ),
}),
}),
],
diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json
index c3809ffaac..85cda09e86 100644
--- a/plugins/gcp-projects/package.json
+++ b/plugins/gcp-projects/package.json
@@ -40,7 +40,7 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
- "@react-hookz/web": "^14.0.0",
+ "@react-hookz/web": "^15.0.0",
"react-router-dom": "6.0.0-beta.0"
},
"peerDependencies": {
diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md
index adc8fb503f..363af1b02f 100644
--- a/plugins/kubernetes-backend/api-report.md
+++ b/plugins/kubernetes-backend/api-report.md
@@ -3,6 +3,7 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
+import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { Duration } from 'luxon';
import { Entity } from '@backstage/catalog-model';
@@ -108,6 +109,7 @@ export class KubernetesBuilder {
protected buildRouter(
objectsProvider: KubernetesObjectsProvider,
clusterSupplier: KubernetesClustersSupplier,
+ catalogApi: CatalogApi,
): express.Router;
// (undocumented)
protected buildServiceLocator(
@@ -155,6 +157,8 @@ export interface KubernetesClustersSupplier {
// @alpha (undocumented)
export interface KubernetesEnvironment {
+ // (undocumented)
+ catalogApi: CatalogApi;
// (undocumented)
config: Config;
// (undocumented)
@@ -268,6 +272,8 @@ export interface ObjectToFetch {
// @alpha (undocumented)
export interface RouterOptions {
+ // (undocumented)
+ catalogApi: CatalogApi;
// (undocumented)
clusterSupplier?: KubernetesClustersSupplier;
// (undocumented)
diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json
index e7d8d2c3c0..337181bfae 100644
--- a/plugins/kubernetes-backend/package.json
+++ b/plugins/kubernetes-backend/package.json
@@ -37,12 +37,14 @@
"dependencies": {
"@azure/identity": "^2.0.4",
"@backstage/backend-common": "^0.14.1-next.2",
+ "@backstage/catalog-client": "^1.0.4-next.1",
"@backstage/catalog-model": "^1.1.0-next.2",
"@backstage/config": "^1.0.1",
"@backstage/errors": "^1.1.0-next.0",
- "@backstage/plugin-kubernetes-common": "^0.4.0-next.1",
+ "@backstage/plugin-auth-node": "^0.2.3-next.1",
+ "@backstage/plugin-kubernetes-common": "^0.4.0-next.0",
"@google-cloud/container": "^4.0.0",
- "@kubernetes/client-node": "^0.16.0",
+ "@kubernetes/client-node": "^0.17.0",
"@types/express": "^4.17.6",
"@types/luxon": "^2.0.4",
"aws-sdk": "^2.840.0",
diff --git a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts
new file mode 100644
index 0000000000..57e6514a96
--- /dev/null
+++ b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { errorHandler } from '@backstage/backend-common';
+import express from 'express';
+import request from 'supertest';
+import Router from 'express-promise-router';
+import { addResourceRoutesToRouter } from './resourcesRoutes';
+import { Entity } from '@backstage/catalog-model';
+
+describe('resourcesRoutes', () => {
+ let app: express.Express;
+
+ beforeAll(() => {
+ app = express();
+ app.use(express.json());
+ const router = Router();
+ addResourceRoutesToRouter(
+ router,
+ {
+ getEntityByRef: jest.fn().mockImplementation(entityRef => {
+ if (entityRef.name === 'noentity') {
+ return Promise.resolve(undefined);
+ }
+ return Promise.resolve({
+ kind: entityRef.kind,
+ metadata: {
+ name: entityRef.name,
+ namespace: entityRef.namespace,
+ },
+ } as Entity);
+ }),
+ } as any,
+ {
+ getKubernetesObjectsByEntity: jest.fn().mockImplementation(args => {
+ if (args.entity.metadata.name === 'inject500') {
+ return Promise.reject(new Error('some internal error'));
+ }
+
+ return Promise.resolve({
+ items: [
+ {
+ clusterOne: {
+ pods: [
+ {
+ metadata: {
+ name: 'pod1',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ });
+ }),
+ getCustomResourcesByEntity: jest.fn().mockImplementation(args => {
+ if (args.entity.metadata.name === 'inject500') {
+ return Promise.reject(new Error('some internal error'));
+ }
+
+ return Promise.resolve({
+ items: [
+ {
+ clusterOne: {
+ pods: [
+ {
+ metadata: {
+ name: 'pod1',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ });
+ }),
+ } as any,
+ );
+ app.use('/', router);
+ app.use(errorHandler());
+ });
+
+ describe('POST /resources/workloads/query', () => {
+ // eslint-disable-next-line jest/expect-expect
+ it('200 happy path', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'kind:namespacec/someComponent',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(200, {
+ items: [
+ {
+ clusterOne: {
+ pods: [
+ {
+ metadata: {
+ name: 'pod1',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when missing entity ref', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: { name: 'InputError', message: 'entity is a required field' },
+ request: {
+ method: 'POST',
+ url: '/resources/workloads/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when bad entity ref', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'ffff',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message:
+ 'Invalid entity ref, Error: Entity reference "ffff" had missing or empty kind (e.g. did not start with "component:" or similar)',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/workloads/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when no entity in catalog', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'noentity:noentity',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message: 'Entity ref missing, noentity:default/noentity',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/workloads/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('401 when no Auth header', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .expect(401, {
+ error: { name: 'AuthenticationError', message: 'No Backstage token' },
+ request: {
+ method: 'POST',
+ url: '/resources/workloads/query',
+ },
+ response: { statusCode: 401 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('401 when invalid Auth header', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'ffffff')
+ .expect(401, {
+ error: { name: 'AuthenticationError', message: 'No Backstage token' },
+ request: {
+ method: 'POST',
+ url: '/resources/workloads/query',
+ },
+ response: { statusCode: 401 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('500 handle gracefully', async () => {
+ await request(app)
+ .post('/resources/workloads/query')
+ .send({
+ entityRef: 'inject500:inject500/inject500',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(500, {
+ error: {
+ name: 'Error',
+ message: 'some internal error',
+ level: 'error',
+ service: 'backstage',
+ },
+ request: { method: 'POST', url: '/resources/workloads/query' },
+ response: { statusCode: 500 },
+ });
+ });
+ });
+ describe('POST /resources/custom/query', () => {
+ // eslint-disable-next-line jest/expect-expect
+ it('200 happy path', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(200, {
+ items: [
+ {
+ clusterOne: {
+ pods: [
+ {
+ metadata: {
+ name: 'pod1',
+ },
+ },
+ ],
+ },
+ },
+ ],
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when missing custom resources', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message: 'customResources is a required field',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when custom resources not array', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ customResources: 'somestring',
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message: 'customResources must be an array',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when custom resources empty', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ customResources: [],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message: 'at least 1 customResource is required',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when missing entity ref', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: { name: 'InputError', message: 'entity is a required field' },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when bad entity ref', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'ffff',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message:
+ 'Invalid entity ref, Error: Entity reference "ffff" had missing or empty kind (e.g. did not start with "component:" or similar)',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('400 when no entity in catalog', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'noentity:noentity',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(400, {
+ error: {
+ name: 'InputError',
+ message: 'Entity ref missing, noentity:default/noentity',
+ },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 400 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('401 when no Auth header', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .expect(401, {
+ error: { name: 'AuthenticationError', message: 'No Backstage token' },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 401 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('401 when invalid Auth header', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'component:someComponent',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'ffffff')
+ .expect(401, {
+ error: { name: 'AuthenticationError', message: 'No Backstage token' },
+ request: {
+ method: 'POST',
+ url: '/resources/custom/query',
+ },
+ response: { statusCode: 401 },
+ });
+ });
+ // eslint-disable-next-line jest/expect-expect
+ it('500 handle gracefully', async () => {
+ await request(app)
+ .post('/resources/custom/query')
+ .send({
+ entityRef: 'inject500:inject500/inject500',
+ auth: {
+ google: 'something',
+ },
+ customResources: [
+ {
+ group: 'someGroup',
+ apiVersion: 'someApiVersion',
+ plural: 'somePlural',
+ },
+ ],
+ })
+ .set('Content-Type', 'application/json')
+ .set('Authorization', 'Bearer Zm9vYmFy')
+ .expect(500, {
+ error: {
+ name: 'Error',
+ message: 'some internal error',
+ level: 'error',
+ service: 'backstage',
+ },
+ request: { method: 'POST', url: '/resources/custom/query' },
+ response: { statusCode: 500 },
+ });
+ });
+ });
+});
diff --git a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts
new file mode 100644
index 0000000000..2b2a48f707
--- /dev/null
+++ b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ CompoundEntityRef,
+ parseEntityRef,
+ stringifyEntityRef,
+} from '@backstage/catalog-model';
+import { CatalogApi } from '@backstage/catalog-client';
+import { InputError, AuthenticationError } from '@backstage/errors';
+import express, { Request } from 'express';
+import { KubernetesObjectsProvider } from '../types/types';
+import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';
+
+export const addResourceRoutesToRouter = (
+ router: express.Router,
+ catalogApi: CatalogApi,
+ objectsProvider: KubernetesObjectsProvider,
+) => {
+ const getEntityByReq = async (req: Request) => {
+ const rawEntityRef = req.body.entityRef;
+ if (rawEntityRef && typeof rawEntityRef !== 'string') {
+ throw new InputError(`entity query must be a string`);
+ } else if (!rawEntityRef) {
+ throw new InputError('entity is a required field');
+ }
+ let entityRef: CompoundEntityRef | undefined = undefined;
+
+ try {
+ entityRef = parseEntityRef(rawEntityRef);
+ } catch (error) {
+ throw new InputError(`Invalid entity ref, ${error}`);
+ }
+
+ const token = getBearerTokenFromAuthorizationHeader(
+ req.headers.authorization,
+ );
+
+ if (!token) {
+ throw new AuthenticationError('No Backstage token');
+ }
+
+ const entity = await catalogApi.getEntityByRef(entityRef, {
+ token: token,
+ });
+
+ if (!entity) {
+ throw new InputError(
+ `Entity ref missing, ${stringifyEntityRef(entityRef)}`,
+ );
+ }
+ return entity;
+ };
+
+ router.post('/resources/workloads/query', async (req, res) => {
+ const entity = await getEntityByReq(req);
+ const response = await objectsProvider.getKubernetesObjectsByEntity({
+ entity,
+ auth: req.body.auth,
+ });
+ res.json(response);
+ });
+
+ router.post('/resources/custom/query', async (req, res) => {
+ const entity = await getEntityByReq(req);
+
+ if (!req.body.customResources) {
+ throw new InputError('customResources is a required field');
+ } else if (!Array.isArray(req.body.customResources)) {
+ throw new InputError('customResources must be an array');
+ } else if (req.body.customResources.length === 0) {
+ throw new InputError('at least 1 customResource is required');
+ }
+
+ const response = await objectsProvider.getCustomResourcesByEntity({
+ entity,
+ customResources: req.body.customResources,
+ auth: req.body.auth,
+ });
+ res.json(response);
+ });
+};
diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts
index ecaf9f3095..309141ec0e 100644
--- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts
+++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.test.ts
@@ -31,11 +31,13 @@ import {
import { KubernetesBuilder } from './KubernetesBuilder';
import { KubernetesFanOutHandler } from './KubernetesFanOutHandler';
import { PodStatus } from '@kubernetes/client-node';
+import { CatalogApi } from '@backstage/catalog-client';
describe('KubernetesBuilder', () => {
let app: express.Express;
let kubernetesFanOutHandler: jest.Mocked;
let config: Config;
+ let catalogApi: CatalogApi;
beforeAll(async () => {
const logger = getVoidLogger();
@@ -69,7 +71,13 @@ describe('KubernetesBuilder', () => {
getKubernetesObjectsByEntity: jest.fn(),
} as any;
- const { router } = await KubernetesBuilder.createBuilder({ config, logger })
+ catalogApi = {} as CatalogApi;
+
+ const { router } = await KubernetesBuilder.createBuilder({
+ config,
+ logger,
+ catalogApi,
+ })
.setObjectsProvider(kubernetesFanOutHandler)
.setClusterSupplier(clusterSupplier)
.build();
@@ -240,6 +248,7 @@ describe('KubernetesBuilder', () => {
const { router } = await KubernetesBuilder.createBuilder({
logger,
config,
+ catalogApi,
})
.setClusterSupplier(clusterSupplier)
.setServiceLocator(serviceLocator)
diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts
index 1b058752c9..59bac4f30a 100644
--- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts
+++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts
@@ -37,6 +37,8 @@ import {
KubernetesFanOutHandler,
} from './KubernetesFanOutHandler';
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
+import { addResourceRoutesToRouter } from '../routes/resourcesRoutes';
+import { CatalogApi } from '@backstage/catalog-client';
/**
*
@@ -45,6 +47,7 @@ import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
export interface KubernetesEnvironment {
logger: Logger;
config: Config;
+ catalogApi: CatalogApi;
}
/**
@@ -119,7 +122,11 @@ export class KubernetesBuilder {
objectTypesToFetch: this.getObjectTypesToFetch(),
});
- const router = this.buildRouter(objectsProvider, clusterSupplier);
+ const router = this.buildRouter(
+ objectsProvider,
+ clusterSupplier,
+ this.env.catalogApi,
+ );
return {
clusterSupplier,
@@ -226,11 +233,13 @@ export class KubernetesBuilder {
protected buildRouter(
objectsProvider: KubernetesObjectsProvider,
clusterSupplier: KubernetesClustersSupplier,
+ catalogApi: CatalogApi,
): express.Router {
const logger = this.env.logger;
const router = Router();
router.use(express.json());
+ // @deprecated
router.post('/services/:serviceId', async (req, res) => {
const serviceId = req.params.serviceId;
const requestBody: ObjectsByEntityRequest = req.body;
@@ -259,6 +268,9 @@ export class KubernetesBuilder {
})),
});
});
+
+ addResourceRoutesToRouter(router, catalogApi, objectsProvider);
+
return router;
}
diff --git a/plugins/kubernetes-backend/src/service/router.ts b/plugins/kubernetes-backend/src/service/router.ts
index 7bd7cca8a9..6c26175058 100644
--- a/plugins/kubernetes-backend/src/service/router.ts
+++ b/plugins/kubernetes-backend/src/service/router.ts
@@ -19,6 +19,7 @@ import { Logger } from 'winston';
import { KubernetesClustersSupplier } from '../types/types';
import express from 'express';
import { KubernetesBuilder } from './KubernetesBuilder';
+import { CatalogApi } from '@backstage/catalog-client';
/**
*
@@ -27,6 +28,7 @@ import { KubernetesBuilder } from './KubernetesBuilder';
export interface RouterOptions {
logger: Logger;
config: Config;
+ catalogApi: CatalogApi;
clusterSupplier?: KubernetesClustersSupplier;
}
diff --git a/plugins/kubernetes-backend/src/service/standaloneApplication.ts b/plugins/kubernetes-backend/src/service/standaloneApplication.ts
index 29262744e5..c12d7be2bb 100644
--- a/plugins/kubernetes-backend/src/service/standaloneApplication.ts
+++ b/plugins/kubernetes-backend/src/service/standaloneApplication.ts
@@ -18,6 +18,7 @@ import {
errorHandler,
notFoundHandler,
requestLoggingHandler,
+ SingleHostDiscovery,
} from '@backstage/backend-common';
import compression from 'compression';
import cors from 'cors';
@@ -26,6 +27,7 @@ import helmet from 'helmet';
import { Logger } from 'winston';
import { createRouter } from './router';
import { ConfigReader } from '@backstage/config';
+import { CatalogClient } from '@backstage/catalog-client';
export interface ApplicationOptions {
enableCors: boolean;
@@ -39,6 +41,10 @@ export async function createStandaloneApplication(
const config = new ConfigReader({});
const app = express();
+ const catalogApi = new CatalogClient({
+ discoveryApi: SingleHostDiscovery.fromConfig(config),
+ });
+
app.use(helmet());
if (enableCors) {
app.use(cors());
@@ -46,7 +52,7 @@ export async function createStandaloneApplication(
app.use(compression());
app.use(express.json());
app.use(requestLoggingHandler());
- app.use('/', await createRouter({ logger, config }));
+ app.use('/', await createRouter({ logger, config, catalogApi }));
app.use(notFoundHandler());
app.use(errorHandler());
diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json
index 9e3ff7299e..09a6d7a32e 100644
--- a/plugins/kubernetes-common/package.json
+++ b/plugins/kubernetes-common/package.json
@@ -38,8 +38,9 @@
"url": "https://github.com/backstage/backstage/issues"
},
"dependencies": {
+ "@backstage/catalog-model": "^1.1.0-next.1",
"@backstage/catalog-model": "^1.1.0-next.2",
- "@kubernetes/client-node": "^0.16.0"
+ "@kubernetes/client-node": "^0.17.0"
},
"devDependencies": {
"@backstage/cli": "^0.18.0-next.2"
diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json
index 0bb8ac0324..f2437dec45 100644
--- a/plugins/kubernetes/package.json
+++ b/plugins/kubernetes/package.json
@@ -41,7 +41,7 @@
"@backstage/plugin-catalog-react": "^1.1.2-next.2",
"@backstage/plugin-kubernetes-common": "^0.4.0-next.1",
"@backstage/theme": "^0.2.16-next.1",
- "@kubernetes/client-node": "^0.16.0",
+ "@kubernetes/client-node": "^0.17.0",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
diff --git a/plugins/kubernetes/src/setupTests.ts b/plugins/kubernetes/src/setupTests.ts
index 28a35d2b06..a373310a1a 100644
--- a/plugins/kubernetes/src/setupTests.ts
+++ b/plugins/kubernetes/src/setupTests.ts
@@ -14,3 +14,14 @@
* limitations under the License.
*/
import '@testing-library/jest-dom';
+// eslint-disable-next-line no-restricted-imports
+import { TextDecoder, TextEncoder } from 'util';
+
+// These are missing from jest-node, so not available on global.
+Object.defineProperty(global, 'TextEncoder', {
+ value: TextEncoder,
+});
+
+Object.defineProperty(global, 'TextDecoder', {
+ value: TextDecoder,
+});
diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md
index 8d302e69f6..2053f01e39 100644
--- a/plugins/scaffolder-backend/api-report.md
+++ b/plugins/scaffolder-backend/api-report.md
@@ -388,6 +388,7 @@ export function createPublishGitlabAction(options: {
gitCommitMessage?: string | undefined;
gitAuthorName?: string | undefined;
gitAuthorEmail?: string | undefined;
+ setUserAsOwner?: boolean | undefined;
}>;
// @public
diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts
index f427023c69..27261ecd49 100644
--- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts
@@ -32,6 +32,9 @@ const mockGitlabClient = {
Users: {
current: jest.fn(),
},
+ ProjectMembers: {
+ add: jest.fn(),
+ },
};
jest.mock('@gitbeaker/node', () => ({
Gitlab: class {
@@ -113,6 +116,7 @@ describe('publish:gitlab', () => {
});
it('should work when there is a token provided through ctx.input', async () => {
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -135,6 +139,7 @@ describe('publish:gitlab', () => {
});
it('should call the correct Gitlab APIs when the owner is an organization', async () => {
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -168,6 +173,7 @@ describe('publish:gitlab', () => {
});
it('should call initRepoAndPush with the correct values', async () => {
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -187,6 +193,7 @@ describe('publish:gitlab', () => {
});
it('should call initRepoAndPush with the correct default branch', async () => {
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -241,6 +248,7 @@ describe('publish:gitlab', () => {
config: customAuthorConfig,
});
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -286,6 +294,7 @@ describe('publish:gitlab', () => {
config: customAuthorConfig,
});
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -305,6 +314,7 @@ describe('publish:gitlab', () => {
});
it('should call output with the remoteUrl and repoContentsUrl', async () => {
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
mockGitlabClient.Projects.create.mockResolvedValue({
http_url_to_repo: 'http://mockurl.git',
@@ -321,4 +331,54 @@ describe('publish:gitlab', () => {
'http://mockurl/-/blob/master',
);
});
+
+ it('should call the correct Gitlab APIs when setUserAsOwner option is true and integration config has a token', async () => {
+ const customAuthorConfig = new ConfigReader({
+ integrations: {
+ gitlab: [
+ {
+ host: 'gitlab.com',
+ token: 'tokenlols',
+ apiBaseUrl: 'https://api.gitlab.com',
+ },
+ ],
+ },
+ });
+
+ const customAuthorIntegrations =
+ ScmIntegrations.fromConfig(customAuthorConfig);
+ const customAuthorAction = createPublishGitlabAction({
+ integrations: customAuthorIntegrations,
+ config: customAuthorConfig,
+ });
+
+ mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 });
+ mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 });
+ mockGitlabClient.Projects.create.mockResolvedValue({
+ id: 123456,
+ http_url_to_repo: 'http://mockurl.git',
+ });
+
+ await customAuthorAction.handler({
+ ...mockContext,
+ input: {
+ repoUrl: 'gitlab.com?repo=repo&owner=owner',
+ token: 'token',
+ setUserAsOwner: true,
+ },
+ });
+
+ expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner');
+ expect(mockGitlabClient.Users.current).toHaveBeenCalled();
+ expect(mockGitlabClient.ProjectMembers.add).toHaveBeenCalledWith(
+ 123456,
+ 12345,
+ 50,
+ );
+ expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({
+ namespace_id: 1234,
+ name: 'repo',
+ visibility: 'private',
+ });
+ });
});
diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts
index a7c247f4d9..4fe55b77a2 100644
--- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts
@@ -43,6 +43,7 @@ export function createPublishGitlabAction(options: {
gitCommitMessage?: string;
gitAuthorName?: string;
gitAuthorEmail?: string;
+ setUserAsOwner?: boolean;
}>({
id: 'publish:gitlab',
description:
@@ -92,6 +93,12 @@ export function createPublishGitlabAction(options: {
type: 'string',
description: 'The token to use for authorization to GitLab',
},
+ setUserAsOwner: {
+ title: 'Set User As Owner',
+ type: 'boolean',
+ description:
+ 'Set the token user as owner of the newly created repository. Requires a token authorized to do the edit in the integration configuration for the matching host',
+ },
},
},
output: {
@@ -116,6 +123,7 @@ export function createPublishGitlabAction(options: {
gitCommitMessage = 'initial commit',
gitAuthorName,
gitAuthorEmail,
+ setUserAsOwner = false,
} = ctx.input;
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
@@ -149,19 +157,35 @@ export function createPublishGitlabAction(options: {
id: number;
};
+ const { id: userId } = (await client.Users.current()) as {
+ id: number;
+ };
+
if (!targetNamespace) {
- const { id } = (await client.Users.current()) as {
- id: number;
- };
- targetNamespace = id;
+ targetNamespace = userId;
}
- const { http_url_to_repo } = await client.Projects.create({
+ const { id: projectId, http_url_to_repo } = await client.Projects.create({
namespace_id: targetNamespace,
name: repo,
visibility: repoVisibility,
});
+ // When setUserAsOwner is true the input token is expected to come from an unprivileged user GitLab
+ // OAuth flow. In this case GitLab works in a way that allows the unprivileged user to
+ // create the repository, but not to push the default protected branch (e.g. master).
+ // In order to set the user as owner of the newly created repository we need to check that the
+ // GitLab integration configuration for the matching host contains a token and use
+ // such token to bootstrap a new privileged client.
+ if (setUserAsOwner && integrationConfig.config.token) {
+ const adminClient = new Gitlab({
+ host: integrationConfig.config.baseUrl,
+ token: integrationConfig.config.token,
+ });
+
+ await adminClient.ProjectMembers.add(projectId, userId, 50);
+ }
+
const remoteUrl = (http_url_to_repo as string).replace(/\.git$/, '');
const repoContentsUrl = `${remoteUrl}/-/blob/${defaultBranch}`;
diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json
index c371c47907..e6223d1952 100644
--- a/plugins/scaffolder/package.json
+++ b/plugins/scaffolder/package.json
@@ -55,7 +55,7 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
- "@react-hookz/web": "^13.0.0",
+ "@react-hookz/web": "^15.0.0",
"@rjsf/core": "^3.2.1",
"@rjsf/material-ui": "^3.2.1",
"@types/json-schema": "^7.0.9",
diff --git a/plugins/tech-radar/README.md b/plugins/tech-radar/README.md
index 10c7a104c1..5c99541c2a 100644
--- a/plugins/tech-radar/README.md
+++ b/plugins/tech-radar/README.md
@@ -90,9 +90,17 @@ export class MyOwnClient implements TechRadarApi {
const data = await fetch('https://mydata.json').then(res => res.json());
- // maybe you'll need to do some data transformation here to make it look like TechRadarLoaderResponse
-
- return data;
+ // For example, this converts the timeline dates into date objects
+ return {
+ ...data,
+ entries: data.entries.map(entry => ({
+ ...entry,
+ timeline: entry.timeline.map(timeline => ({
+ ...timeline,
+ date: new Date(timeline.date),
+ })),
+ })),
+ };
}
}
diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json
index e089428dbe..7668143599 100644
--- a/plugins/techdocs-module-addons-contrib/package.json
+++ b/plugins/techdocs-module-addons-contrib/package.json
@@ -43,7 +43,7 @@
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
- "@react-hookz/web": "^14.0.0",
+ "@react-hookz/web": "^15.0.0",
"git-url-parse": "^12.0.0",
"react-use": "^17.2.4"
},
diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts
index 0d40ebb60a..21a307b65a 100644
--- a/scripts/api-extractor.ts
+++ b/scripts/api-extractor.ts
@@ -219,8 +219,6 @@ const ALLOW_WARNINGS = [
'plugins/circleci',
'plugins/cloudbuild',
'plugins/code-climate',
- 'plugins/code-coverage',
- 'plugins/code-coverage-backend',
'plugins/config-schema',
'plugins/cost-insights',
'plugins/dynatrace',
diff --git a/yarn.lock b/yarn.lock
index 8f09b76887..f06a187ebf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -344,17 +344,17 @@
dependencies:
debug "^4.1.1"
-"@azure/msal-common@^7.0.0":
- version "7.0.0"
- resolved "https://registry.npmjs.org/@azure/msal-common/-/msal-common-7.0.0.tgz#f4b52c6d9591cf8720dcb24c1d21fce2d186f871"
- integrity sha512-EkaHGjv0kw1RljhboeffM91b+v9d5VtmyG+0a/gvdqjbLu3kDzEfoaS5BNM9QqMzbxgZylsjAjQDtxdHLX/ziA==
+"@azure/msal-common@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/@azure/msal-common/-/msal-common-7.1.0.tgz#b77dbf9ae581f1ed254f81d56422e3cdd6664b32"
+ integrity sha512-WyfqE5mY/rggjqvq0Q5DxLnA33KSb0vfsUjxa95rycFknI03L5GPYI4HTU9D+g0PL5TtsQGnV3xzAGq9BFCVJQ==
"@azure/msal-node@^1.1.0", "@azure/msal-node@^1.3.0":
- version "1.10.0"
- resolved "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.10.0.tgz#ee3a26201c4899cc6928cc331c31d3568d3cb728"
- integrity sha512-oSv9mg199FpRTe+fZ3o9NDYpKShOHqeceaNcCHJcKUaAaCojAbfbxD1Cvsti8BEsLKE6x0HcnjilnM1MKmZekA==
+ version "1.11.0"
+ resolved "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.11.0.tgz#d8bd3f15c1f05bf806ba6f9479c48c2eddd6a98d"
+ integrity sha512-KW/XEexfCrPzdYbjY7NVmhq9okZT3Jvck55CGXpz9W5asxeq3EtrP45p+ZXtQVEfko0YJdolpCNqWUyXvanWZg==
dependencies:
- "@azure/msal-common" "^7.0.0"
+ "@azure/msal-common" "^7.1.0"
jsonwebtoken "^8.5.1"
uuid "^8.3.0"
@@ -2288,9 +2288,9 @@
xcase "^2.0.1"
"@google-cloud/container@^4.0.0":
- version "4.0.1"
- resolved "https://registry.npmjs.org/@google-cloud/container/-/container-4.0.1.tgz#a3206d3030539e09b7beee8f351fad86c77af79d"
- integrity sha512-JpsOsdKnCQm1b5aVNnO/2Urdg+qbCLi/srEnTupRj73Pu5wXLHXOCe3vy8Z2GvyCqu7qr89fMREQ4kO4QijnHA==
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/@google-cloud/container/-/container-4.1.0.tgz#cf929184f668fc40ca8b864b7f638228ae67fc98"
+ integrity sha512-LpVT3wxG73iX/5deF4a2KIEZ7sULF2mksrzyA25OVGtyxFclSZT2Gs5uho5USSLkoKg/Ou+l+ekGMrgBQbLDag==
dependencies:
google-gax "^3.0.1"
@@ -3528,10 +3528,10 @@
dependencies:
ioredis "^5.1.0"
-"@kubernetes/client-node@^0.16.0":
- version "0.16.3"
- resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.16.3.tgz#a26a5abbd6e45603b4f75f0baff00e19853e5be7"
- integrity sha512-L7IckuyuPfhd+/Urib8MRas9D6sfKEq8IaITYcaE6LlU+Y8MeD7MTbuW6Yb2WdeRuFN8HPSS47mxPnOUNYBXEg==
+"@kubernetes/client-node@^0.17.0":
+ version "0.17.0"
+ resolved "https://registry.npmjs.org/@kubernetes/client-node/-/client-node-0.17.0.tgz#cbf69ff6c8a311c1461275169612ac46db00fe3f"
+ integrity sha512-oKQfRf7RPpJIF2Ft92g6jefbW3Mddf6IzcfpBNDWrAy66LmyAWds6fQTMsdutGPuXV6KD29u6RfM3rdzddGMIA==
dependencies:
"@types/js-yaml" "^4.0.1"
"@types/node" "^10.12.0"
@@ -3545,7 +3545,7 @@
isomorphic-ws "^4.0.1"
js-yaml "^4.1.0"
jsonpath-plus "^0.19.0"
- openid-client "^4.1.1"
+ openid-client "^5.1.6"
request "^2.88.0"
rfc4648 "^1.3.0"
shelljs "^0.8.5"
@@ -4438,9 +4438,9 @@
react-is "^16.8.0 || ^17.0.0"
"@maxim_mazurok/gapi.client.calendar@^3.0.20220408":
- version "3.0.20220624"
- resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220624.tgz#17817142e348ce811415dfb111299fbdac2450a0"
- integrity sha512-5+x4A6l8GY+dojvXUBQGc0Y4JOm9lBY1YZfCAEEZPjBcXkx0vs/CenPnmAu/fwQgGSrQLipxFV+pS6RL3L28mg==
+ version "3.0.20220701"
+ resolved "https://registry.npmjs.org/@maxim_mazurok/gapi.client.calendar/-/gapi.client.calendar-3.0.20220701.tgz#4ee9089e8164269743e61ec36e79e095aa0926b6"
+ integrity sha512-3CjbVZysFdUmGWZwjYGsV3z+kViaVpiWvgR7/DX5nUtb1YWIaS0jNUCch1YVN9aDFaCWuI3UV/STveSPvUspgw==
dependencies:
"@types/gapi.client" "*"
@@ -5271,11 +5271,6 @@
resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.4.tgz#a167e46c10d05a07ab299fc518793b0cff8f6924"
integrity sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==
-"@panva/asn1.js@^1.0.0":
- version "1.0.0"
- resolved "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz#dd55ae7b8129e02049f009408b97c61ccf9032f6"
- integrity sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==
-
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@@ -5329,18 +5324,11 @@
resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
-"@react-hookz/deep-equal@^1.0.1", "@react-hookz/deep-equal@^1.0.2":
+"@react-hookz/deep-equal@^1.0.2":
version "1.0.2"
resolved "https://registry.npmjs.org/@react-hookz/deep-equal/-/deep-equal-1.0.2.tgz#4e8bdeda027379dcf8b62a42e5f75f0351b11b35"
integrity sha512-cM5kPFb6EFH5q52WzRxfRX9+8g5kq78McWOYs6e1seo+nK6NpfLupT5uOCIJp37jU8ayd4Su8ni3HRFTN2C2kg==
-"@react-hookz/web@^13.0.0":
- version "13.3.0"
- resolved "https://registry.npmjs.org/@react-hookz/web/-/web-13.3.0.tgz#257e31049e92a121912fe1e67bdd01dbec5a203b"
- integrity sha512-KswgkmqBVVDo6UnBFfssrojmDisogxC4jGZmd976R8YHoS3zdQJxjqICpOBSRohbRyYhYS9Cprw7BuV/CZcMaw==
- dependencies:
- "@react-hookz/deep-equal" "^1.0.1"
-
"@react-hookz/web@^14.0.0":
version "14.7.1"
resolved "https://registry.npmjs.org/@react-hookz/web/-/web-14.7.1.tgz#5e39e6fc21331cc4ae95f36e8135ad763e6c29fb"
@@ -5348,6 +5336,13 @@
dependencies:
"@react-hookz/deep-equal" "^1.0.2"
+"@react-hookz/web@^15.0.0":
+ version "15.0.1"
+ resolved "https://registry.npmjs.org/@react-hookz/web/-/web-15.0.1.tgz#a6e5460dd16e54ccc0b899e1eed4ae29e871060f"
+ integrity sha512-nvVLUsDFv3fpZcINoy3I4MeaX8+yoKU21m2Ey2g0VAVqOMp+0GBBC6OHkzT2lRa2fiPIVuJwlmboSKQt7segfQ==
+ dependencies:
+ "@react-hookz/deep-equal" "^1.0.2"
+
"@repeaterjs/repeater@^3.0.4":
version "3.0.4"
resolved "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"
@@ -7496,9 +7491,9 @@
eslint-visitor-keys "^3.0.0"
"@uiw/react-codemirror@^4.9.3":
- version "4.9.5"
- resolved "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.9.5.tgz#0f66c09dfc355baef5a7020f206da8db90bae223"
- integrity sha512-KHgP/PII9Gv4iEUzbdO95qpSSPy27iSHzxQ01mBPWC4UvzuA0eQY2h64gzi/ld68esbKMGYoevgOBPCRJwNN1A==
+ version "4.10.4"
+ resolved "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.10.4.tgz#f26833d5cfc4c63de1858c587218efd9f85f18e2"
+ integrity sha512-eMl/Xtmhhjo1Hmx0P1NgwVlviOUCdjSYPKHn0bgUG6aLgZjCo1l0MJDDuLikGp8YlDrXcDKgiuXPt4GykBaUmg==
dependencies:
"@babel/runtime" ">=7.11.0"
"@codemirror/theme-one-dark" "^6.0.0"
@@ -7853,13 +7848,6 @@ anafanafo@2.0.0:
dependencies:
char-width-table-consumer "^1.0.0"
-ansi-align@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
- integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
- dependencies:
- string-width "^3.0.0"
-
ansi-colors@^4.1.1, ansi-colors@^4.1.3:
version "4.1.3"
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
@@ -8423,9 +8411,9 @@ aws-sdk-mock@^5.2.1:
traverse "^0.6.6"
aws-sdk@^2.1122.0, aws-sdk@^2.840.0, aws-sdk@^2.948.0:
- version "2.1167.0"
- resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1167.0.tgz#e8614bce1a7355782734b6928792f14d11b39231"
- integrity sha512-hUJzAqWVfNYpct1S+GjyPIc2s+GZcAhbWVqIG4qbLYZ3+sBTcjv3lLH5zx7K+qcTGINDU0g4EsMi6hIrAU+blg==
+ version "2.1168.0"
+ resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1168.0.tgz#7936459edee0c999065f1ecf2ef0bea89ea056c1"
+ integrity sha512-9+WYoYTHHjLqeWdSSLbNpmc/NgnZpX4LGiyYjXenh4WNRBXshXI0XioTK8BQgDscVzB978EJV8kG1nZGE3USzw==
dependencies:
buffer "4.9.2"
events "1.1.1"
@@ -8946,20 +8934,6 @@ bottleneck@^2.15.3:
resolved "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91"
integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==
-boxen@^5.0.0:
- version "5.1.2"
- resolved "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
- integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==
- dependencies:
- ansi-align "^3.0.0"
- camelcase "^6.2.0"
- chalk "^4.1.0"
- cli-boxes "^2.2.1"
- string-width "^4.2.2"
- type-fest "^0.20.2"
- widest-line "^3.1.0"
- wrap-ansi "^7.0.0"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -9678,11 +9652,6 @@ clean-stack@^2.0.0:
resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
-cli-boxes@^2.2.1:
- version "2.2.1"
- resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
- integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
-
cli-cursor@^2.0.0, cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
@@ -10231,18 +10200,6 @@ config-chain@^1.1.12:
ini "^1.3.4"
proto-list "~1.2.1"
-configstore@^5.0.1:
- version "5.0.1"
- resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
- integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
- dependencies:
- dot-prop "^5.2.0"
- graceful-fs "^4.1.2"
- make-dir "^3.0.0"
- unique-string "^2.0.0"
- write-file-atomic "^3.0.0"
- xdg-basedir "^4.0.0"
-
connect-history-api-fallback@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8"
@@ -10674,11 +10631,6 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
-crypto-random-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
- integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
-
css-box-model@^1.2.0:
version "1.2.1"
resolved "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1"
@@ -11779,7 +11731,7 @@ dot-case@^3.0.4:
no-case "^3.0.4"
tslib "^2.0.3"
-dot-prop@^5.1.0, dot-prop@^5.2.0:
+dot-prop@^5.1.0:
version "5.3.0"
resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
@@ -11922,11 +11874,6 @@ emittery@^0.8.1:
resolved "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
-emoji-regex@^7.0.1:
- version "7.0.3"
- resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
- integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
@@ -12299,11 +12246,6 @@ escalade@^3.1.1:
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
-escape-goat@^2.0.0:
- version "2.1.1"
- resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
- integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==
-
escape-html@^1.0.3, escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -14199,23 +14141,6 @@ got@11.8.3:
p-cancelable "^2.0.0"
responselike "^2.0.0"
-got@^11.8.0:
- version "11.8.5"
- resolved "https://registry.npmjs.org/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046"
- integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==
- dependencies:
- "@sindresorhus/is" "^4.0.0"
- "@szmarczak/http-timer" "^4.0.5"
- "@types/cacheable-request" "^6.0.1"
- "@types/responselike" "^1.0.0"
- cacheable-lookup "^5.0.3"
- cacheable-request "^7.0.2"
- decompress-response "^6.0.0"
- http2-wrapper "^1.0.0-beta.5.2"
- lowercase-keys "^2.0.0"
- p-cancelable "^2.0.0"
- responselike "^2.0.0"
-
got@^9.6.0:
version "9.6.0"
resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
@@ -14517,11 +14442,6 @@ has-values@^1.0.0:
is-number "^3.0.0"
kind-of "^4.0.0"
-has-yarn@^2.1.0:
- version "2.1.0"
- resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
- integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
-
has@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
@@ -15027,11 +14947,6 @@ import-from@^3.0.0:
dependencies:
resolve-from "^5.0.0"
-import-lazy@^2.1.0:
- version "2.1.0"
- resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
- integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
import-lazy@~4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
@@ -15553,7 +15468,7 @@ is-in-browser@^1.0.2, is-in-browser@^1.1.3:
resolved "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
integrity sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=
-is-installed-globally@^0.4.0, is-installed-globally@~0.4.0:
+is-installed-globally@~0.4.0:
version "0.4.0"
resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
@@ -15593,11 +15508,6 @@ is-node-process@^1.0.1:
resolved "https://registry.npmjs.org/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23"
integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ==
-is-npm@^5.0.0:
- version "5.0.0"
- resolved "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8"
- integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==
-
is-number-object@^1.0.4:
version "1.0.7"
resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
@@ -15880,11 +15790,6 @@ is-wsl@^2.2.0:
dependencies:
is-docker "^2.0.0"
-is-yarn-global@^0.3.0:
- version "0.3.0"
- resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
- integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
@@ -16543,13 +16448,6 @@ joi@^17.4.0:
"@sideway/formula" "^3.0.0"
"@sideway/pinpoint" "^2.0.0"
-jose@^2.0.5:
- version "2.0.5"
- resolved "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz#29746a18d9fff7dcf9d5d2a6f62cb0c7cd27abd3"
- integrity sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==
- dependencies:
- "@panva/asn1.js" "^1.0.0"
-
jose@^4.1.4:
version "4.5.0"
resolved "https://registry.npmjs.org/jose/-/jose-4.5.0.tgz#92829d8cf846351eb55aaaf94f252fb1d191f2d5"
@@ -17196,7 +17094,7 @@ language-tags@^1.0.5:
dependencies:
language-subtag-registry "~0.3.2"
-latest-version@5.1.0, latest-version@^5.1.0:
+latest-version@5.1.0:
version "5.1.0"
resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
@@ -17802,9 +17700,9 @@ log-update@^4.0.0:
wrap-ansi "^6.2.0"
logform@^2.3.2, logform@^2.4.0:
- version "2.4.1"
- resolved "https://registry.npmjs.org/logform/-/logform-2.4.1.tgz#512c9eaef738044d1c619790ba0f806c80d9d3a9"
- integrity sha512-7XB/tqc3VRbri9pRjU6E97mQ8vC27ivJ3lct4jhyT+n0JNDd4YKldFl0D75NqDp46hk8RC7Ma1Vjv/UPf67S+A==
+ version "2.4.2"
+ resolved "https://registry.npmjs.org/logform/-/logform-2.4.2.tgz#a617983ac0334d0c3b942c34945380062795b47c"
+ integrity sha512-W4c9himeAwXEdZ05dQNerhFz2XG80P9Oj0loPUMV23VC2it0orMHQhJm4hdnnor3rd1HsGf6a2lPwBM1zeXHGw==
dependencies:
"@colors/colors" "1.5.0"
fecha "^4.2.0"
@@ -17952,7 +17850,7 @@ make-dir@^3.0.0, make-dir@^3.1.0:
dependencies:
semver "^6.0.0"
-make-error@^1, make-error@^1.1.1, make-error@^1.3.6:
+make-error@^1, make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
@@ -19342,9 +19240,9 @@ node-releases@^2.0.1:
integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
nodemon@^2.0.2:
- version "2.0.18"
- resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.18.tgz#0f5a3aa7b4587f2626e6f01369deba89cb0462a2"
- integrity sha512-uAvrKipi2zAz8E7nkSz4qW4F4zd5fs2wNGsTx+xXlP8KXqd9ucE0vY9wankOsPboeDyuUGN9vsXGV1pLn80l/A==
+ version "2.0.19"
+ resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.19.tgz#cac175f74b9cb8b57e770d47841995eebe4488bd"
+ integrity sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==
dependencies:
chokidar "^3.5.2"
debug "^3.2.7"
@@ -19352,10 +19250,10 @@ nodemon@^2.0.2:
minimatch "^3.0.4"
pstree.remy "^1.1.8"
semver "^5.7.1"
+ simple-update-notifier "^1.0.7"
supports-color "^5.5.0"
touch "^3.1.0"
undefsafe "^2.0.5"
- update-notifier "^5.1.0"
nopt@1.0.10, nopt@~1.0.10:
version "1.0.10"
@@ -19873,20 +19771,7 @@ openapi-types@^12.0.0:
resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-12.0.0.tgz#458a99d048f9eae1c067e15d56a8bfb3726041f1"
integrity sha512-6Wd9k8nmGQHgCbehZCP6wwWcfXcvinhybUTBatuhjRsCxUIujuYFZc9QnGeae75CyHASewBtxs0HX/qwREReUw==
-openid-client@^4.1.1:
- version "4.9.0"
- resolved "https://registry.npmjs.org/openid-client/-/openid-client-4.9.0.tgz#bdfc9194435316df419f759ce177635146b43074"
- integrity sha512-ThBbvRUUZwxUKBVK2UpDNIZ3eJkvtqWI8s5Dm+naV+gJdL+yRhT+8ywqct1gy5uL+xVS5+A/nhFcpJIisH2x6Q==
- dependencies:
- aggregate-error "^3.1.0"
- got "^11.8.0"
- jose "^2.0.5"
- lru-cache "^6.0.0"
- make-error "^1.3.6"
- object-hash "^2.0.1"
- oidc-token-hash "^5.0.1"
-
-openid-client@^5.1.3:
+openid-client@^5.1.3, openid-client@^5.1.6:
version "5.1.8"
resolved "https://registry.npmjs.org/openid-client/-/openid-client-5.1.8.tgz#3a24910288b32c32f548fb6e391f44178ce6370f"
integrity sha512-EPxJY6bT7YIYQEXSGxRC5flQ3GUhLy98ufdto6+BVBrFGPmwjUpy4xBcYuU/Wt9nPkO/3EgljBrr6Ezx4lp1RQ==
@@ -20535,10 +20420,10 @@ path-case@^3.0.4:
dot-case "^3.0.4"
tslib "^2.0.3"
-path-equal@1.1.2:
- version "1.1.2"
- resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.1.2.tgz#260e7c449c4c2022f68cc5fa6e617e892858250d"
- integrity sha512-p5kxPPwCdbf5AdXzT1bUBJomhgBlEjRBavYNr1XUpMFIE4Hnf2roueCMXudZK5tnaAu1tTmp3GPzqwJK45IHEA==
+path-equal@^1.1.2:
+ version "1.2.2"
+ resolved "https://registry.npmjs.org/path-equal/-/path-equal-1.2.2.tgz#fa2997f0a829de22ec8f5f86461ca5590d49b832"
+ integrity sha512-AUJvbcle1Zgb1TgtftHYknlrgrSYyI1ytrYgSbKUHSybwqUDnbD2cw9PIWivuMvsN+GTXmr/DRN4VBXpHG6aGg==
path-exists@^2.0.0:
version "2.1.0"
@@ -21581,17 +21466,10 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-pupa@^2.1.1:
- version "2.1.1"
- resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
- integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
- dependencies:
- escape-goat "^2.0.0"
-
puppeteer@^15.0.0:
- version "15.2.0"
- resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-15.2.0.tgz#9cd81334f9c6a2e1c972b5a7ecf3f18ab3bfb978"
- integrity sha512-6Mzj5pbq4J4DxJE5o6V+arrOB9Gma0CxOLP1zKYMrMR7AYuNaPzsK7pBrpDwI64W6Mxk5G7NqiLSFTrgSzR1zg==
+ version "15.3.1"
+ resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-15.3.1.tgz#0ff9b433a8fc3798f5ec82ea4b31ec47857219cf"
+ integrity sha512-Z+SpYBiS1zUzMXV7Wnhe2pyuVCFAFRTq1UrUWHB2CkLos5v7bXvXYuZ3Fn5pSN5IObxijyx4opNYKTCRnGni6Q==
dependencies:
cross-fetch "3.1.5"
debug "4.3.4"
@@ -23227,13 +23105,6 @@ semver-compare@^1.0.0:
resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
-semver-diff@^3.1.1:
- version "3.1.1"
- resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
- integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==
- dependencies:
- semver "^6.3.0"
-
semver-store@^0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9"
@@ -23244,7 +23115,7 @@ semver-store@^0.3.0:
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-semver@7.0.0:
+semver@7.0.0, semver@~7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
@@ -23515,6 +23386,13 @@ simple-swizzle@^0.2.2:
dependencies:
is-arrayish "^0.3.1"
+simple-update-notifier@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc"
+ integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==
+ dependencies:
+ semver "~7.0.0"
+
sinon@^13.0.2:
version "13.0.2"
resolved "https://registry.npmjs.org/sinon/-/sinon-13.0.2.tgz#c6a8ddd655dc1415bbdc5ebf0e5b287806850c3a"
@@ -24186,7 +24064,7 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -24203,15 +24081,6 @@ string-width@^2.1.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
-string-width@^3.0.0:
- version "3.1.0"
- resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
- integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
- dependencies:
- emoji-regex "^7.0.1"
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^5.1.0"
-
string-width@^5.0.0:
version "5.1.2"
resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
@@ -24267,7 +24136,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
-strip-ansi@5.2.0, strip-ansi@^5.1.0:
+strip-ansi@5.2.0:
version "5.2.0"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
@@ -25349,15 +25218,15 @@ typedarray@^0.0.6:
resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-typescript-json-schema@^0.53.0:
- version "0.53.1"
- resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.1.tgz#9204547f3e145169b40928998366ff6d28b81d32"
- integrity sha512-Hg+RnOKUd38MOzC0rDft03a8xvwO+gCcj1F77smw2tCoZYQpFoLtrXWBGdvCX+REliko5WYel2kux17HPFqjLQ==
+typescript-json-schema@^0.54.0:
+ version "0.54.0"
+ resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.54.0.tgz#b3fc42ad90df6a0f6ab57571ebc8b4d41125df4f"
+ integrity sha512-/MNhm1pjdxXiVspjjyRCrQAA1B768cRzHU83aIqN5vQqQEW2NgyyKOfcguiRIMM64lseIZIelegnHOHEu7YDCg==
dependencies:
"@types/json-schema" "^7.0.9"
"@types/node" "^16.9.2"
glob "^7.1.7"
- path-equal "1.1.2"
+ path-equal "^1.1.2"
safe-stable-stringify "^2.2.0"
ts-node "^10.2.1"
typescript "~4.6.0"
@@ -25510,13 +25379,6 @@ unique-slug@^2.0.0:
dependencies:
imurmurhash "^0.1.4"
-unique-string@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
- integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
- dependencies:
- crypto-random-string "^2.0.0"
-
unist-builder@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04"
@@ -25664,26 +25526,6 @@ upath@^2.0.1:
resolved "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b"
integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==
-update-notifier@^5.1.0:
- version "5.1.0"
- resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9"
- integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==
- dependencies:
- boxen "^5.0.0"
- chalk "^4.1.0"
- configstore "^5.0.1"
- has-yarn "^2.1.0"
- import-lazy "^2.1.0"
- is-ci "^2.0.0"
- is-installed-globally "^0.4.0"
- is-npm "^5.0.0"
- is-yarn-global "^0.3.0"
- latest-version "^5.1.0"
- pupa "^2.1.1"
- semver "^7.3.4"
- semver-diff "^3.1.1"
- xdg-basedir "^4.0.0"
-
upper-case-first@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324"
@@ -25995,9 +25837,9 @@ vm-browserify@^1.0.1:
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
vm2@^3.9.6:
- version "3.9.9"
- resolved "https://registry.npmjs.org/vm2/-/vm2-3.9.9.tgz#c0507bc5fbb99388fad837d228badaaeb499ddc5"
- integrity sha512-xwTm7NLh/uOjARRBs8/95H0e8fT3Ukw5D/JJWhxMbhKzNh1Nu981jQKvkep9iKYNxzlVrdzD0mlBGkDKZWprlw==
+ version "3.9.10"
+ resolved "https://registry.npmjs.org/vm2/-/vm2-3.9.10.tgz#c66543096b5c44c8861a6465805c23c7cc996a44"
+ integrity sha512-AuECTSvwu2OHLAZYhG716YzwodKCIJxB6u1zG7PgSQwIgAlEaoXH52bxdcvT8GkGjnYK7r7yWDW0m0sOsPuBjQ==
dependencies:
acorn "^8.7.0"
acorn-walk "^8.2.0"
@@ -26311,13 +26153,6 @@ wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
dependencies:
string-width "^1.0.2 || 2 || 3 || 4"
-widest-line@^3.1.0:
- version "3.1.0"
- resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
- integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==
- dependencies:
- string-width "^4.0.0"
-
window-size@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
@@ -26489,11 +26324,6 @@ xcase@^2.0.1:
resolved "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz#c7fa72caa0f440db78fd5673432038ac984450b9"
integrity sha1-x/pyyqD0QNt4/VZzQyA4rJhEULk=
-xdg-basedir@^4.0.0:
- version "4.0.0"
- resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
- integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
xhr@^2.0.1:
version "2.6.0"
resolved "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d"