diff --git a/.changeset/brave-pugs-fold.md b/.changeset/brave-pugs-fold.md
new file mode 100644
index 0000000000..f79867a719
--- /dev/null
+++ b/.changeset/brave-pugs-fold.md
@@ -0,0 +1,5 @@
+---
+'@backstage/test-utils': patch
+---
+
+Add new `MockConfigApi` as a more discoverable and leaner method for mocking configuration.
diff --git a/.changeset/clean-wolves-jog.md b/.changeset/clean-wolves-jog.md
new file mode 100644
index 0000000000..70ab23715f
--- /dev/null
+++ b/.changeset/clean-wolves-jog.md
@@ -0,0 +1,5 @@
+---
+'@backstage/config': patch
+---
+
+The `ConfigReader#get` method now always returns a deep clone of the configuration data.
diff --git a/.changeset/cold-steaks-flash.md b/.changeset/cold-steaks-flash.md
new file mode 100644
index 0000000000..74cdcbdec2
--- /dev/null
+++ b/.changeset/cold-steaks-flash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+fix: Register plugin to prioritise Component kind for entityRef
diff --git a/.changeset/dry-boats-tap.md b/.changeset/dry-boats-tap.md
new file mode 100644
index 0000000000..c69c4360b5
--- /dev/null
+++ b/.changeset/dry-boats-tap.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-todo-backend': patch
+---
+
+Properly exported all referenced types
diff --git a/.changeset/eight-rats-raise.md b/.changeset/eight-rats-raise.md
new file mode 100644
index 0000000000..7bc2a07f04
--- /dev/null
+++ b/.changeset/eight-rats-raise.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Add catalog permission rules.
diff --git a/.changeset/fair-bikes-scream.md b/.changeset/fair-bikes-scream.md
new file mode 100644
index 0000000000..decdfd3828
--- /dev/null
+++ b/.changeset/fair-bikes-scream.md
@@ -0,0 +1,28 @@
+---
+'@backstage/cli': minor
+---
+
+ESLint upgraded to version 8 and all it's plugins updated to newest version.
+
+If you use any custom plugins for ESLint please check compatibility.
+
+```diff
+- "@typescript-eslint/eslint-plugin": "^v4.33.0",
+- "@typescript-eslint/parser": "^v4.28.3",
++ "@typescript-eslint/eslint-plugin": "^5.9.0",
++ "@typescript-eslint/parser": "^5.9.0",
+- "eslint": "^7.30.0",
++ "eslint": "^8.6.0",
+- "eslint-plugin-import": "^2.20.2",
+- "eslint-plugin-jest": "^24.1.0",
+- "eslint-plugin-jsx-a11y": "^6.2.1",
++ "eslint-plugin-import": "^2.25.4",
++ "eslint-plugin-jest": "^25.3.4",
++ "eslint-plugin-jsx-a11y": "^6.5.1",
+- "eslint-plugin-react": "^7.12.4",
+- "eslint-plugin-react-hooks": "^4.0.0",
++ "eslint-plugin-react": "^7.28.0",
++ "eslint-plugin-react-hooks": "^4.3.0",
+```
+
+Please consult changelogs from packages if you find any problems.
diff --git a/.changeset/funny-llamas-yell.md b/.changeset/funny-llamas-yell.md
new file mode 100644
index 0000000000..890caaa221
--- /dev/null
+++ b/.changeset/funny-llamas-yell.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-graphql': patch
+---
+
+Bump graphql versions
diff --git a/.changeset/fuzzy-llamas-collect.md b/.changeset/fuzzy-llamas-collect.md
new file mode 100644
index 0000000000..17ee925e56
--- /dev/null
+++ b/.changeset/fuzzy-llamas-collect.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend-module-ldap': patch
+---
+
+Make sure to avoid accidental data sharing / mutation of `set` values
diff --git a/.changeset/healthy-toes-laugh.md b/.changeset/healthy-toes-laugh.md
new file mode 100644
index 0000000000..e0db38e5e3
--- /dev/null
+++ b/.changeset/healthy-toes-laugh.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-permission-node': patch
+---
+
+Add helpers for creating PermissionRules with inferred types
diff --git a/.changeset/lazy-gorillas-tell.md b/.changeset/lazy-gorillas-tell.md
new file mode 100644
index 0000000000..672d8c221b
--- /dev/null
+++ b/.changeset/lazy-gorillas-tell.md
@@ -0,0 +1,7 @@
+---
+'@backstage/core-plugin-api': minor
+---
+
+Removed previously deprecated exports: `PluginHooks`, `PluginOutput`, and `FeatureFlagOutput`.
+
+The deprecated `register` method of `PluginConfig` has been removed, as well as the deprecated `output` method of `BackstagePlugin`.
diff --git a/.changeset/long-otters-promise.md b/.changeset/long-otters-promise.md
new file mode 100644
index 0000000000..eecb97e8ac
--- /dev/null
+++ b/.changeset/long-otters-promise.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-catalog-backend-module-ldap': patch
+'@backstage/plugin-catalog-backend-module-msgraph': patch
+---
+
+Clean up API report
diff --git a/.changeset/nervous-starfishes-report.md b/.changeset/nervous-starfishes-report.md
new file mode 100644
index 0000000000..2ac4179a2c
--- /dev/null
+++ b/.changeset/nervous-starfishes-report.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-home': patch
+---
+
+Adds two new home components - CompanyLogo and Toolkit.
diff --git a/.changeset/olive-points-flash.md b/.changeset/olive-points-flash.md
new file mode 100644
index 0000000000..64b23419de
--- /dev/null
+++ b/.changeset/olive-points-flash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Switch Webpack minification to use `esbuild` instead of `terser`.
diff --git a/.changeset/plenty-eyes-brush.md b/.changeset/plenty-eyes-brush.md
new file mode 100644
index 0000000000..354c216c3c
--- /dev/null
+++ b/.changeset/plenty-eyes-brush.md
@@ -0,0 +1,60 @@
+---
+'@backstage/create-app': patch
+---
+
+Add permissions to create-app's PluginEnvironment
+
+`CatalogEnvironment` now has a `permissions` field, which means that a permission client must now be provided as part of `PluginEnvironment`. To apply these changes to an existing app, add the following to the `makeCreateEnv` function in `packages/backend/src/index.ts`:
+
+```diff
+ // packages/backend/src/index.ts
+
++ import { ServerPermissionClient } from '@backstage/plugin-permission-node';
+
+ function makeCreateEnv(config: Config) {
+ ...
++ const permissions = ServerPerimssionClient.fromConfig(config, {
++ discovery,
++ tokenManager,
++ });
+
+ root.info(`Created UrlReader ${reader}`);
+
+ return (plugin: string): PluginEnvironment => {
+ ...
+ return {
+ logger,
+ cache,
+ database,
+ config,
+ reader,
+ discovery,
+ tokenManager,
+ scheduler,
++ permissions,
+ };
+ }
+ }
+```
+
+And add a permissions field to the `PluginEnvironment` type in `packages/backend/src/types.ts`:
+
+```diff
+ // packages/backend/src/types.ts
+
++ import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
+
+ export type PluginEnvironment = {
+ ...
++ permissions: PermissionAuthorizer;
+ };
+```
+
+[`@backstage/plugin-permission-common`](https://www.npmjs.com/package/@backstage/plugin-permission-common) and [`@backstage/plugin-permission-node`](https://www.npmjs.com/package/@backstage/plugin-permission-node) will need to be installed as dependencies:
+
+```diff
+ // packages/backend/package.json
+
++ "@backstage/plugin-permission-common": "...",
++ "@backstage/plugin-permission-node": "...",
+```
diff --git a/.changeset/popular-cycles-work.md b/.changeset/popular-cycles-work.md
new file mode 100644
index 0000000000..939f59de94
--- /dev/null
+++ b/.changeset/popular-cycles-work.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+bump `logform` to use fixed version of `color` dependency
diff --git a/.changeset/rotten-files-wink.md b/.changeset/rotten-files-wink.md
new file mode 100644
index 0000000000..65bd92bcc5
--- /dev/null
+++ b/.changeset/rotten-files-wink.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Updated `ResponseErrorPanel` to not use the deprecated `data` property of `ResponseError`.
diff --git a/.changeset/rotten-olives-shop.md b/.changeset/rotten-olives-shop.md
new file mode 100644
index 0000000000..b7fb51ad06
--- /dev/null
+++ b/.changeset/rotten-olives-shop.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Update `config/eslint.js` to forbid imports of `@material-ui/icons/` as well.
diff --git a/.changeset/short-shoes-fail.md b/.changeset/short-shoes-fail.md
new file mode 100644
index 0000000000..0b45d67a32
--- /dev/null
+++ b/.changeset/short-shoes-fail.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-auth-backend': patch
+---
+
+Removed `@backstage/test-utils` dependency.
diff --git a/.changeset/silver-falcons-nail.md b/.changeset/silver-falcons-nail.md
new file mode 100644
index 0000000000..970bbd7fee
--- /dev/null
+++ b/.changeset/silver-falcons-nail.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Add apply-conditions endpoint for evaluating conditional permissions in catalog backend.
diff --git a/.changeset/silver-mice-bake.md b/.changeset/silver-mice-bake.md
new file mode 100644
index 0000000000..6cba2fdb0a
--- /dev/null
+++ b/.changeset/silver-mice-bake.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-app-api': minor
+---
+
+Removed previously deprecated `ApiRegistry` export.
diff --git a/.changeset/techdocs-light-onions-cover.md b/.changeset/techdocs-light-onions-cover.md
new file mode 100644
index 0000000000..55c0873575
--- /dev/null
+++ b/.changeset/techdocs-light-onions-cover.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-techdocs': patch
+---
+
+Fix an issue where the TechDocs sidebar is hidden when the Backstage sidebar is pinned at smaller screen sizes
diff --git a/.changeset/three-sheep-sparkle.md b/.changeset/three-sheep-sparkle.md
new file mode 100644
index 0000000000..db6d8148ce
--- /dev/null
+++ b/.changeset/three-sheep-sparkle.md
@@ -0,0 +1,7 @@
+---
+'@backstage/plugin-catalog-backend': minor
+---
+
+In order to integrate the permissions system with the refresh endpoint in catalog-backend, a new AuthorizedRefreshService was created as a thin wrapper around the existing refresh service which performs authorization and handles the case when authorization is denied. In order to instantiate AuthorizedRefreshService, a permission client is required, which was added as a new field to `CatalogEnvironment`.
+
+The new `permissions` field in `CatalogEnvironment` should already receive the permission client from the `PluginEnvrionment`, so there should be no changes required to the catalog backend setup. See [the create-app changelog](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md) for more details.
diff --git a/.changeset/twelve-panthers-move.md b/.changeset/twelve-panthers-move.md
new file mode 100644
index 0000000000..f52050a488
--- /dev/null
+++ b/.changeset/twelve-panthers-move.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+Clean up API reports
diff --git a/.changeset/violet-dingos-relate.md b/.changeset/violet-dingos-relate.md
new file mode 100644
index 0000000000..c8b0c03e2c
--- /dev/null
+++ b/.changeset/violet-dingos-relate.md
@@ -0,0 +1,7 @@
+---
+'@backstage/errors': minor
+---
+
+Removed the deprecated exports `ErrorResponse` and `parseErrorResponse`.
+
+Removed the deprecated `constructor` and the deprecated `data` property of `ResponseError`.
diff --git a/.changeset/warm-crews-flash.md b/.changeset/warm-crews-flash.md
new file mode 100644
index 0000000000..b21a3ada02
--- /dev/null
+++ b/.changeset/warm-crews-flash.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-kubernetes-backend': patch
+---
+
+Exclude the AWS session token from credential validation, because it's not necessary in this context.
diff --git a/.changeset/warm-moles-battle.md b/.changeset/warm-moles-battle.md
new file mode 100644
index 0000000000..3d203ea1d3
--- /dev/null
+++ b/.changeset/warm-moles-battle.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-tech-insights': patch
+---
+
+fix React warning because of missing `key` prop
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 59847fd65f..65a4b1a438 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,7 +5,7 @@ updates:
schedule:
interval: daily
time: '04:00'
- open-pull-requests-limit: 5
+ open-pull-requests-limit: 10
labels:
- dependencies
- package-ecosystem: npm
@@ -13,6 +13,6 @@ updates:
schedule:
interval: daily
time: '04:00'
- open-pull-requests-limit: 2
+ open-pull-requests-limit: 5
labels:
- dependencies
diff --git a/.github/workflows/chromatic-storybook-test.yml b/.github/workflows/chromatic-storybook-test.yml
index 4c64db309d..355ad65bee 100644
--- a/.github/workflows/chromatic-storybook-test.yml
+++ b/.github/workflows/chromatic-storybook-test.yml
@@ -4,6 +4,14 @@ on:
paths:
- '.github/workflows/chromatic-storybook-test.yml'
- 'packages/storybook/**'
+ - 'packages/config/src/**'
+ - 'packages/theme/src/**'
+ - 'packages/types/src/**'
+ - 'packages/errors/src/**'
+ - 'packages/version-bridge/src/**'
+ - 'packages/test-utils/src/**'
+ - 'packages/core-app-api/src/**'
+ - 'packages/core-plugin-api/src/**'
- 'packages/core-components/src/**'
- '**/*.stories.tsx'
diff --git a/.gitignore b/.gitignore
index 8c37280023..60d0d6da3b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -136,3 +136,6 @@ site
# e2e tests
cypress/cypress/*
+
+# Possible leftover from build:api-reports
+tsconfig.tmp.json
diff --git a/ADOPTERS.md b/ADOPTERS.md
index e0e6a818c6..b35f6a3d77 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -77,5 +77,6 @@
| [Mox Bank](https://www.mox.com/) | [Nick Laqua](https://github.com/nick-laqua-dragon), [Gauthier Roebroeck](https://github.com/gauthier-roebroeck-mox) | "Single pane of glass" developer portal for providing a best-in-class developer experience to our product teams and making Mox the best tech environment in Hongkong 🥰🚀 |
| [Keyloop](https://www.keyloop.com/) | [Andre Wanlin](https://github.com/awanlin) | Future-motive Developer Portal to help our teams create technology to make everything about buying and owning a car better. 🚗 |
| [Simply Business](https://sbtech.simplybusiness.co.uk/) | [@addersuk](https://github.com/addersuk), [@LightningStairs](https://github.com/LightningStairs), [@punitcse](https://github.com/punitcse), [@moltenice](https://github.com/moltenice) | Central developer portal to access everything a developer needs such as docs, internal service catalog, and the ability to quickly create a new service from a template. Internally developed Backstage plugins allow us to customise the experience to how we work. |
-| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding |
-| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. |
+| [Overwolf](https://www.overwolf.com) | [@tomwolfgang](https://github.com/tomwolfgang) | Dev portal - software catalog, tech-docs, scaffolding |
+| [Hotmart](https://www.hotmart.com) | [@fabioviana-hotmart](https://github.com/fabioviana-hotmart) | The main Developers Portal to centralize docs, applications and technical metrics. |
+| [EF Education First](https://www.ef.com) | [Daan Boerlage](https://github.com/runebaas), [Rafał Nowosielski](https://github.com/rnowosielski) | Our developer portal - primarily used for cataloging and scaffolding with the ambition to expand with more feature adoptions over time |
diff --git a/docs/assets/architecture-overview/package-architecture.drawio b/docs/assets/architecture-overview/package-architecture.drawio
deleted file mode 100644
index c320c94c69..0000000000
--- a/docs/assets/architecture-overview/package-architecture.drawio
+++ /dev/null
@@ -1 +0,0 @@
-7V3bktq4Fv0aHknhCwYe06Q7kzmdOZ2kp2ZyXk4JW4AntkXZopvO149sZLAt+YKvEiFVU4OFcdtaa2svSXtvj7Sle/jog932M7KgM1In1mGkfRipqqLMDfK/sOXt2DIPj8KGjW9b9KRzwzf7J6SNE9q6ty0YpE7ECDnY3qUbTeR50MSpNuD76DV92ho56b+6AxvINHwzgcO2/mVbeEtb1fnk/MVv0N5s6Z82DPrFCpg/Nj7ae/TvjVRtHf07fu2C+Fr0/GALLPSaaNLuR9rSRwgfP7mHJXTCvo277fi7h5xvT/ftQw9X+cHBgb9bB924/+ur+fXpXg2e/sFjZaodr/MCnD2MHyS6XfwWd1H0kDC8zGSk3b1ubQy/7YAZfvtKSEHatth1yJFCPgLH3njkswPX5LbuXqCPbdLb72kzRuH5a9txlshBPmnxkEeudMc+Dn3C8ArwkGiij/cRIhdi/42cEn+7oF1NqTiNOfaaAHZC27YJTBWNNgJKps3p2ucOJR9on17Qvwud6U1oEf7RQ/rs6Q5GPt6iDfKA84jC3oq69R+I8Ru1HrDHKN3p8GDjvxOfv4eXejelRx8O9MrRwVt84JEH/Dt5kPhVeHj+WXQU/26NPBxjRzg/if5FZ1nvQ3skzSsHmT+et7Z3bH6wnfhGAwx8TB9DP36bOMrlQID2vkn7788v8AG9HVYfPj/O0cvy95+fNto4HjmAv4G44DzK9hCDQkb50AHYfkmPEa2zQ4kJmkOPMxPuz63tseXMkO9JgnDZ0iHq5t5/iR5HaZsC1p+H5fjnf9RP31+8P/bgiwV/fh+rhmAcYAfccg6k+qwjQiiFhLj24YPLndlMLO7EXBaCO7Pqo0keeWbXwh4uXDN1KPYU3XZC+YHdrpn420HfJjcH/fAU29vQX2VFoGtbVkTFjFgMjr96jI4+zM8t5EjNyEaCvgXgfG1GwProB0x8Y5hzuFqfvomFfaGDqa4zMzJT1VmZOeeozM5EpqJoAg0DzUcBKQcBtaILmeqCuZB5Iwmq9DdhkQV27nmDCYf/Pn9Z6v9b2IuvfzyZS//ZmE2+xEN//fGiPaFQVWW+U6epUaLCGPEAXNsJG57BFrmAttIbVJQ+KJXBu9uhRR9STaiMmggXyEifyKQo1uu1anIVhWWsjKnRk6LQJ0MrCs4qoGQTi8x4ocioKTThJxZ89miNp6UDr4GqUkrQqnSZikaXmTB0UavypYYckZYvymArpkW3nVAaO2e/sb3xSDWAG+oHJ3T9tJFcKm7e4FN3ySFHLl7g0GKNSx9PLaBeC7JFnZWvhCizfpdCGo8lXQmXX2g5fXbJhEUgP1S8WdunH5rV9ENSylwOXQTzQzl8mQrDl3oyV87tlqp0GU7mFt12Tdky/hVWUwaWL7xll87kS5FDTHDkLoZ98mivfODbMGAoELzargOiSKKkzU0SAJqkl6DPgfoYj9VCZ56CreLOXLCdeYqFSwVfTbvqzSnTmyM9CtsjvUSGBPWB2tTYRK6LvCszLRbTQspVt5o0zhrHZrpaq+Q+gFEVZQwDPN5j22Et6IZ0BaRnQyPNetA8pEHw4wZyLZAVXsxsryjPGZSXdHgW3QUqEz2zHmJU9IEn22q9NxdlNmMCDBy0GZuOHT65REZjTeHc0nlGM1dXmnGB0cwvRTprNByt06/RxFabjzN+23Hs5gavDBJHYUP1slaMvLW9ucErpa6JI8Dz4YW+j/yb9UqqaBROjhXfCbvH9LobzDVgng4NMy+VLg2zTRToxgfYlmuxQRyQh3fFKrvc8OAjgmu0Rvc+DKCfLJEPGXyFmKGUCxv+Ep3SWXeysz1G2fhwDHY78p8tldGU791XNJoT5aTVr2rpLDQE2IJrsHewXDJHHJT7lLE5sRcMcr0ms160I0oOnmKmxG2p/UnO7mX5luflqaz8RTxOZFaRPxVlQ1y9EaA7AvC7fCgCFN52UTGJYAt24UfSU87bnR+u2OPyUT2dcLR27N1vowvqTQRUbEWkaEFHLeYZXcoRUpyhd7robuxd1LC9buLefonIlMLcPoFDU3IimeqM3ANHvqUJI3zEfmXCiBUpWXjbDWOZwuWuvQMzP6KNMsdtix74pBiZCSInbrvvFPY6acji+i85h6OZ+KGVOROPQesoXZRC1FchpUSIuK4bSXaWxYhHR9m5UQ+kGi6LsfC+6zq5a3VutZKSAjLLM7f0xjYOCAL6+VQVMbaNoVwgJ/a3ZxfI0O0U9/SMkBPiIeSeAhP1pHBWIrnT4TaCnrhdWb7f6ki1lwAVawpnPJNbGDMN8DfgCkkmw1ZCjqsXtdZRxfy+k/eVI7+vMBFL3GlrDncaJ/gNWyfrWrkjmBwsvO+EU7k/EAdAwCetT5EIHAkfojybZhauq0Yot5Klk1OCuprORngL/XGe2vYhMOWKXq6zc1zMzAskW5lTV3llsrtz6hXXE4spIF8WV63Aqm44wNPs/XKgYlmPYg54yGJDrwRmQK3En24YwIuT7ZcCxqABJJct+w5Q9bxwJVa64gmTOhvWg0zdhCp9X5kEUszHGhfQGLhucSJOQYbqK81GEMEmZPF9JwSDLLOwqVY+C+Muq7UyC+MXg2cTCC/a7bjG+Vebe/TFFG5x5nba2GhbsnFpwwZ2X8Saq5yyiU8bXqh4r7Rhsz4uos0VzvLEJw03j7Ir1hQKkMLw4nz/niZIauM5tSOd3Kq2QLAtF+gXbKdltp05gcM61/F3ViBCL0xoOymq3nLaipGvTd7Bi1Hp1TLd6JD3yya76dInu+mlyW5yFqISCOPBKzbMSkvLWfDlBrHcVRvYTamEY+x3haElp6hOB/SK3IlAafG+RMmEq1xjqGhPilR13bhQlw6Zkf4xkbtDHumMaxs4q803+qLD4CpJZUfXrEraQleqWb5A1j58LQCtQirwhoC5Y7skb1KtTkzkedDEYBVfYXJJp3BfB89bwGjldfD8aoycQbARwytlPyd5St84X1FinGEsZ+JwvTrnzLiufdxoDFf1dRIOlmpnBsJuQ8kEZYvhPI2h5EZ09Qklp2ilRFC2GJvXGEpeem6vUKoMlMk1YiLaIsmWAZc8K04jmO5K6oo43qnEq50Q5hEmTanU+j3LgO4Q1ErHVaVfCFk99ilALvJ3W9u8gVgJRN7bzfoFsej9IDcEyxHkzYu6QpD7CHIr1RbzEFtQqv05xZwIVgbL5eOnmyFW9IdDW6Kiyz3VqDVrrJH+m1lD4VRZ7hk2uacVtWaIjWEzepzX58DGTiFkgq3WbLC5tc0Hh63CMq7IsPUzSBrCDZIGg5KYbyYNgxofgGs7YcMz2CIX0Fb6ZxRlJGjexElAlKdexVZUmjkR022RIVQb9ddzbo2zDyeRgffkTg3h3Gnjcq83Ay83cKWygVdNrBvAwNvecrxK4ZX14MMLr5kkBt6oAqa0I0N11z8VdmSIVaoAFCupmdmoSri0HKvufcTlmN64rO/Aw9hVM0y9AoYZ7MLSErk7gO2V7dj4jeGfBMvwydS/SQvyhoGDk3am8Eq9dKdvjAo7YXEHP4IVdJ5QYEcvziOmgjBGLgeBY7hbEln6shH3sCEwbN+tQGCb785Dyv+xbwNvw6ktUi1ct5r15++WpbM+FVb+nnbcfIQBffxxGMrZkuxVSmVv/GKRVCjf4mJajMKIEYQT330MEfkcvfBSu/8X
\ No newline at end of file
diff --git a/docs/assets/architecture-overview/package-architecture.drawio.svg b/docs/assets/architecture-overview/package-architecture.drawio.svg
new file mode 100644
index 0000000000..df8c0f8820
--- /dev/null
+++ b/docs/assets/architecture-overview/package-architecture.drawio.svg
@@ -0,0 +1,746 @@
+
diff --git a/docs/assets/architecture-overview/package-architecture.png b/docs/assets/architecture-overview/package-architecture.png
deleted file mode 100644
index dfa48fb13b..0000000000
Binary files a/docs/assets/architecture-overview/package-architecture.png and /dev/null differ
diff --git a/docs/auth/bitbucket/provider.md b/docs/auth/bitbucket/provider.md
index 63dfb815e0..ee87c2d4e6 100644
--- a/docs/auth/bitbucket/provider.md
+++ b/docs/auth/bitbucket/provider.md
@@ -50,3 +50,41 @@ The Bitbucket provider is a structure with two configuration keys:
To add the provider to the frontend, add the `bitbucketAuthApi` reference and
`SignInPage` component as shown in
[Adding the provider to the sign-in page](../index.md#adding-the-provider-to-the-sign-in-page).
+
+## Using Bitbucket for sign-in
+
+In order to use the Bitbucket provider for sign-in, you must configure it with a
+`signIn.resolver`. See the
+[Sign-In Resolver documentation](../identity-resolver.md) for more details on
+how this is done. Note that for the Bitbucket provider, you'll want to use
+`bitbucket` as the provider ID, and `createBitbucketProvider` for the provider
+factory.
+
+The `@backstage/plugin-auth-backend` plugin also comes with two built-in
+resolves that can be used if desired. The first one is the
+`bitbucketUsernameSignInResolver`, which identifies users by matching their
+Bitbucket username to `bitbucket.org/username` annotations of `User` entities in
+the catalog. Note that you must populate your catalog with matching entities or
+users will not be able to sign in.
+
+The second resolver is the `bitbucketUsernameSignInResolver`, which works the
+same way, but uses the Bitbucket user ID instead, and matches on the
+`bitbucket.org/user-id` annotation.
+
+The following is an example of how to use one of the built-in resolvers:
+
+```ts
+import {
+ createBitbucketProvider,
+ bitbucketUsernameSignInResolver,
+} from '@backstage/plugin-auth-backend';
+
+// ...
+ providerFactories: {
+ bitbucket: createBitbucketProvider({
+ signIn: {
+ resolver: bitbucketUsernameSignInResolver,
+ },
+ }),
+ },
+```
diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md
index 4ba44b8ef4..a3c42c682c 100644
--- a/docs/features/search/how-to-guides.md
+++ b/docs/features/search/how-to-guides.md
@@ -97,3 +97,37 @@ of the `SearchType` component.
...
```
+
+## How to limit what can be searched in the Software Catalog
+
+The Software Catalog includes a wealth of information about the components,
+systems, groups, users, and other aspects of your software ecosystem. However,
+you may not always want _every_ aspect to appear when a user searches the
+catalog. Examples include:
+
+- Entities of kind `Location`, which are often not useful to Backstage users.
+- Entities of kind `User` or `Group`, if you'd prefer that users and groups be
+ exposed to search in a different way (or not at all).
+
+It's possible to write your own [Collator](./concepts.md#collators) to control
+exactly what's available to search, (or a [Decorator](./concepts.md#decorators)
+to filter things out here and there), but the `DefaultCatalogCollator` that's
+provided by `@backstage/plugin-catalog-backend` offers some configuration too!
+
+```diff
+// packages/backend/src/plugins/search.ts
+
+indexBuilder.addCollator({
+ defaultRefreshIntervalSeconds: 600,
+ collator: DefaultCatalogCollator.fromConfig(config, {
+ discovery,
+ tokenManager,
++ filter: {
++ kind: ['API', 'Component', 'Domain', 'Group', 'System', 'User'],
++ },
+ }),
+});
+```
+
+As shown above, you can add a catalog entity filter to narrow down what catalog
+entities are indexed by the search engine.
diff --git a/docs/features/techdocs/getting-started.md b/docs/features/techdocs/getting-started.md
index d79f6bb891..37e135d1dc 100644
--- a/docs/features/techdocs/getting-started.md
+++ b/docs/features/techdocs/getting-started.md
@@ -230,7 +230,7 @@ You can do so by including the following lines in the last step of your
```Dockerfile
RUN apt-get update && apt-get install -y python3 python3-pip
-RUN pip3 install mkdocs-techdocs-core==0.0.16
+RUN pip3 install mkdocs-techdocs-core==0.2.2
```
Please be aware that the version requirement could change, you need to check our
diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md
index b9b74f92dd..d05a14cc35 100644
--- a/docs/getting-started/app-custom-theme.md
+++ b/docs/getting-started/app-custom-theme.md
@@ -253,3 +253,73 @@ const LogoFull = () => {
return ;
};
```
+
+## Custom Homepage
+
+In addition to a custom theme, a custom logo, you can also customize the
+homepage of your app. To do that we need to go through a few steps.
+
+### Setting up the Home Page
+
+1. Create a Home Page Component that will be used for composition.
+
+`packages/app/src/components/home/HomePage.tsx`
+
+```tsx
+import React from 'react';
+
+export const HomePage = () => {
+ return {
+ /* TODO: Compose a Home Page here */
+ };
+};
+```
+
+2. Add a route where the homepage will live, presumably `/`.
+
+`packages/app/src/App.tsx`
+
+```tsx
+import { HomepageCompositionRoot } from '@backstage/plugin-home';
+import { HomePage } from './components/home/HomePage';
+
+// ...
+}>
+
+;
+// ...
+```
+
+### Composing your Home Page
+
+Composing a Home Page is no different from creating a regular React Component,
+i.e. the App Integrator is free to include whatever content they like. However,
+there are components developed with the Home Page in mind. If you are looking
+for components to use when composing your homepage, you can take a look at the
+[collection of Homepage components](https://backstage.io/?path=/story/plugins-home-components)
+in storybook. If you don't find a component that suits your needs but want to
+contribute, check the
+[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing).
+
+!!! tip If you want to use one of the available homepage templates you can find
+the
+[templates](https://backstage.io/storybook/?path=/story/plugins-home-templates)
+in the storybook under the "Home" plugin. And if you would like to contribute a
+template, please see the
+[Contributing documentation](https://github.com/backstage/backstage/blob/master/plugins/home/README.md#contributing)
+
+```tsx
+import React from 'react';
+import Grid from '@material-ui/core/Grid';
+import { HomePageCompanyLogo } from '@backstage/plugin-home';
+
+export const HomePage = () => {
+ return (
+
+
+
+
+
+ );
+};
+```
diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md
index 744316cf11..d3f171e4f8 100644
--- a/docs/overview/architecture-overview.md
+++ b/docs/overview/architecture-overview.md
@@ -179,13 +179,7 @@ Surrounding the plugin are different package groups which are the different
possible interface points of the plugin. Note that not all library package lists
are complete as packages have been omitted for brevity.
-
-
-
+
### Overview
diff --git a/package.json b/package.json
index 57cf603090..7d2b7a1882 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"start": "yarn workspace example-app start",
"start-backend": "yarn workspace example-backend start",
"build": "lerna run build",
- "build:api-reports": "yarn tsc:full && yarn build:api-reports:only",
+ "build:api-reports": "yarn build:api-reports:only --tsc",
"build:api-reports:only": "ts-node -T -P scripts/tsconfig.json scripts/api-extractor.ts",
"build:api-docs": "yarn build:api-reports --docs",
"tsc": "tsc",
@@ -68,7 +68,7 @@
"@types/webpack": "^5.28.0",
"command-exists": "^1.2.9",
"cross-env": "^7.0.0",
- "concurrently": "^6.0.0",
+ "concurrently": "^7.0.0",
"eslint-plugin-notice": "^0.9.10",
"fs-extra": "9.1.0",
"husky": "^6.0.0",
diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md
index a62a280dc9..d63416571d 100644
--- a/packages/backend-common/api-report.md
+++ b/packages/backend-common/api-report.md
@@ -34,9 +34,7 @@ import { Server } from 'http';
import * as winston from 'winston';
import { Writable } from 'stream';
-// Warning: (ae-missing-release-tag) "AwsS3UrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export class AwsS3UrlReader implements UrlReader {
constructor(
integration: AwsS3Integration,
@@ -59,7 +57,7 @@ export class AwsS3UrlReader implements UrlReader {
toString(): string;
}
-// @public (undocumented)
+// @public
export class AzureUrlReader implements UrlReader {
constructor(
integration: AzureIntegration,
@@ -114,12 +112,12 @@ export interface CacheClient {
): Promise;
}
-// @public (undocumented)
+// @public
export type CacheClientOptions = {
defaultTtl?: number;
};
-// @public (undocumented)
+// @public
export type CacheClientSetOptions = {
ttl?: number;
};
@@ -133,18 +131,17 @@ export class CacheManager {
): CacheManager;
}
-// @public (undocumented)
+// @public
export type CacheManagerOptions = {
logger?: Logger_2;
onError?: (err: Error) => void;
};
-// @public (undocumented)
+// @public
export const coloredFormat: winston.Logform.Format;
-// @public (undocumented)
+// @public
export interface ContainerRunner {
- // (undocumented)
runContainer(opts: RunContainerOptions): Promise;
}
@@ -157,7 +154,7 @@ export function createDatabaseClient(
overrides?: Partial,
): Knex;
-// @public (undocumented)
+// @public
export function createRootLogger(
options?: winston.LoggerOptions,
env?: NodeJS.ProcessEnv,
@@ -166,14 +163,14 @@ export function createRootLogger(
// @public
export function createServiceBuilder(_module: NodeModule): ServiceBuilder;
-// @public (undocumented)
+// @public
export function createStatusCheckRouter(options: {
logger: Logger_2;
path?: string;
statusCheck?: StatusCheck;
}): Promise;
-// @public (undocumented)
+// @public
export class DatabaseManager {
forPlugin(pluginId: string): PluginDatabaseManager;
static fromConfig(
@@ -187,7 +184,7 @@ export type DatabaseManagerOptions = {
migrations?: PluginDatabaseManager['migrations'];
};
-// @public (undocumented)
+// @public
export class DockerContainerRunner implements ContainerRunner {
constructor(options: { dockerClient: Docker });
// (undocumented)
@@ -205,7 +202,7 @@ export function errorHandler(
options?: ErrorHandlerOptions,
): ErrorRequestHandler;
-// @public (undocumented)
+// @public
export type ErrorHandlerOptions = {
showStackTraces?: boolean;
logger?: Logger_2;
@@ -218,13 +215,13 @@ export type FromReadableArrayOptions = Array<{
path: string;
}>;
-// @public (undocumented)
+// @public
export function getRootLogger(): winston.Logger;
// @public
export function getVoidLogger(): winston.Logger;
-// @public (undocumented)
+// @public
export class Git {
// (undocumented)
add(options: { dir: string; filepath: string }): Promise;
@@ -310,7 +307,7 @@ export class GithubUrlReader implements UrlReader {
toString(): string;
}
-// @public (undocumented)
+// @public
export class GitlabUrlReader implements UrlReader {
constructor(
integration: GitLabIntegration,
@@ -398,7 +395,7 @@ export type ReadTreeResponseDirOptions = {
targetDir?: string;
};
-// @public (undocumented)
+// @public
export interface ReadTreeResponseFactory {
// (undocumented)
fromReadableArray(
@@ -448,7 +445,7 @@ export type ReadUrlResponse = {
// @public
export function requestLoggingHandler(logger?: Logger_2): RequestHandler;
-// @public (undocumented)
+// @public
export type RequestLoggingHandlerFactory = (
logger?: Logger_2,
) => RequestHandler;
@@ -459,7 +456,7 @@ export function resolvePackagePath(name: string, ...paths: string[]): string;
// @public
export function resolveSafeChildPath(base: string, path: string): string;
-// @public (undocumented)
+// @public
export type RunContainerOptions = {
imageName: string;
command?: string | string[];
@@ -508,7 +505,7 @@ export class ServerTokenManager implements TokenManager {
static noop(): TokenManager;
}
-// @public (undocumented)
+// @public
export type ServiceBuilder = {
loadConfig(config: Config): ServiceBuilder;
setPort(port: number): ServiceBuilder;
@@ -534,7 +531,7 @@ export type ServiceBuilder = {
start(): Promise;
};
-// @public (undocumented)
+// @public
export function setRootLogger(newLogger: winston.Logger): void;
// @public @deprecated
@@ -554,7 +551,7 @@ export class SingleHostDiscovery implements PluginEndpointDiscovery {
getExternalBaseUrl(pluginId: string): Promise;
}
-// @public (undocumented)
+// @public
export type StatusCheck = () => Promise;
// @public
@@ -562,7 +559,7 @@ export function statusCheckHandler(
options?: StatusCheckHandlerOptions,
): Promise;
-// @public (undocumented)
+// @public
export interface StatusCheckHandlerOptions {
statusCheck?: StatusCheck;
}
@@ -597,7 +594,7 @@ export class UrlReaders {
static default(options: UrlReadersOptions): UrlReader;
}
-// @public (undocumented)
+// @public
export type UrlReadersOptions = {
config: Config;
logger: Logger_2;
@@ -612,8 +609,4 @@ export function useHotCleanup(
// @public
export function useHotMemoize(_module: NodeModule, valueFactory: () => T): T;
-
-// Warnings were encountered during analysis:
-//
-// src/database/types.d.ts:23:12 - (tsdoc-undefined-tag) The TSDoc tag "@default" is not defined in this configuration
```
diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json
index adbb6fed18..7165992607 100644
--- a/packages/backend-common/package.json
+++ b/packages/backend-common/package.json
@@ -58,7 +58,7 @@
"keyv-memcache": "^1.2.5",
"knex": "^0.95.1",
"lodash": "^4.17.21",
- "logform": "^2.1.1",
+ "logform": "^2.3.2",
"minimatch": "^3.0.4",
"minimist": "^1.2.5",
"morgan": "^1.10.0",
diff --git a/packages/backend-common/src/cache/CacheClient.ts b/packages/backend-common/src/cache/CacheClient.ts
index 8e046f7f19..96982edeaa 100644
--- a/packages/backend-common/src/cache/CacheClient.ts
+++ b/packages/backend-common/src/cache/CacheClient.ts
@@ -22,7 +22,11 @@ type CacheClientArgs = {
client: Keyv;
};
-/** @public */
+/**
+ * Options passed to {@link CacheClient.set}.
+ *
+ * @public
+ */
export type CacheClientSetOptions = {
/**
* Optional TTL in milliseconds. Defaults to the TTL provided when the client
diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts
index 896c08fb94..66e9849e77 100644
--- a/packages/backend-common/src/cache/CacheManager.ts
+++ b/packages/backend-common/src/cache/CacheManager.ts
@@ -55,8 +55,8 @@ export class CacheManager {
private readonly errorHandler: CacheManagerOptions['onError'];
/**
- * Creates a new CacheManager instance by reading from the `backend` config
- * section, specifically the `.cache` key.
+ * Creates a new {@link CacheManager} instance by reading from the `backend`
+ * config section, specifically the `.cache` key.
*
* @param config - The loaded application configuration.
*/
@@ -93,7 +93,8 @@ export class CacheManager {
/**
* Generates a PluginCacheManager for consumption by plugins.
*
- * @param pluginId - The plugin that the cache manager should be created for. Plugin names should be unique.
+ * @param pluginId - The plugin that the cache manager should be created for.
+ * Plugin names should be unique.
*/
forPlugin(pluginId: string): PluginCacheManager {
return {
diff --git a/packages/backend-common/src/cache/types.ts b/packages/backend-common/src/cache/types.ts
index 70c46770a8..5cf8323c52 100644
--- a/packages/backend-common/src/cache/types.ts
+++ b/packages/backend-common/src/cache/types.ts
@@ -17,7 +17,11 @@
import { Logger } from 'winston';
import { CacheClient } from './CacheClient';
-/** @public */
+/**
+ * Options given when constructing a {@link CacheClient}.
+ *
+ * @public
+ */
export type CacheClientOptions = {
/**
* An optional default TTL (in milliseconds) to be set when getting a client
@@ -27,7 +31,11 @@ export type CacheClientOptions = {
defaultTtl?: number;
};
-/** @public */
+/**
+ * Options given when constructing a {@link CacheManager}.
+ *
+ * @public
+ */
export type CacheManagerOptions = {
/**
* An optional logger for use by the PluginCacheManager.
@@ -42,17 +50,19 @@ export type CacheManagerOptions = {
};
/**
- * The PluginCacheManager manages access to cache stores that Plugins get.
+ * Manages access to cache stores that plugins get.
*
* @public
*/
export type PluginCacheManager = {
/**
- * getClient provides backend plugins cache connections for itself.
+ * Provides backend plugins cache connections for themselves.
*
- * The purpose of this method is to allow plugins to get isolated data
- * stores so that plugins are discouraged from cache-level integration
- * and/or cache key collisions.
+ * @remarks
+ *
+ * The purpose of this method is to allow plugins to get isolated data stores
+ * so that plugins are discouraged from cache-level integration and/or cache
+ * key collisions.
*/
getClient: (options?: CacheClientOptions) => CacheClient;
};
diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts
index 5959c60c83..3aadd30148 100644
--- a/packages/backend-common/src/database/DatabaseManager.ts
+++ b/packages/backend-common/src/database/DatabaseManager.ts
@@ -38,7 +38,7 @@ function pluginPath(pluginId: string): string {
}
/**
- * Configuration options object.
+ * Creation options for {@link DatabaseManager}.
*
* @public
*/
@@ -46,15 +46,20 @@ export type DatabaseManagerOptions = {
migrations?: PluginDatabaseManager['migrations'];
};
-/** @public */
+/**
+ * Manages database connections for Backstage backend plugins.
+ *
+ * The database manager allows the user to set connection and client settings on
+ * a per pluginId basis by defining a database config block under
+ * `plugin.` in addition to top level defaults. Optionally, a user may
+ * set `prefix` which is used to prefix generated database names if config is
+ * not provided.
+ *
+ * @public
+ */
export class DatabaseManager {
/**
- * Creates a DatabaseManager from `backend.database` config.
- *
- * The database manager allows the user to set connection and client settings on a per pluginId
- * basis by defining a database config block under `plugin.` in addition to top level
- * defaults. Optionally, a user may set `prefix` which is used to prefix generated database
- * names if config is not provided.
+ * Creates a {@link DatabaseManager} from `backend.database` config.
*
* @param config - The loaded application configuration.
* @param options - An optional configuration object.
@@ -108,7 +113,7 @@ export class DatabaseManager {
* which is the pluginId prefixed with 'backstage_plugin_'. If `pluginDivisionMode` is
* `schema`, it will fallback to using the default database for the knex instance.
*
- * @param pluginId Lookup the database name for given plugin
+ * @param pluginId - Lookup the database name for given plugin
* @returns String representing the plugin's database name
*/
private getDatabaseName(pluginId: string): string | undefined {
@@ -143,12 +148,13 @@ export class DatabaseManager {
/**
* Provides the client type which should be used for a given plugin.
*
- * The client type is determined by plugin specific config if present. Otherwise the base
- * client is used as the fallback.
+ * The client type is determined by plugin specific config if present.
+ * Otherwise the base client is used as the fallback.
*
- * @param pluginId Plugin to get the client type for
- * @returns Object with client type returned as `client` and boolean representing whether
- * or not the client was overridden as `overridden`
+ * @param pluginId - Plugin to get the client type for
+ * @returns Object with client type returned as `client` and boolean
+ * representing whether or not the client was overridden as
+ * `overridden`
*/
private getClientType(pluginId: string): {
client: string;
@@ -169,8 +175,8 @@ export class DatabaseManager {
/**
* Provides the knexConfig which should be used for a given plugin.
*
- * @param pluginId Plugin to get the knexConfig for
- * @returns the merged kexConfig value or undefined if it isn't specified
+ * @param pluginId - Plugin to get the knexConfig for
+ * @returns The merged knexConfig value or undefined if it isn't specified
*/
private getAdditionalKnexConfig(pluginId: string): JsonObject | undefined {
const pluginConfig = this.config
@@ -197,13 +203,15 @@ export class DatabaseManager {
}
/**
- * Provides a Knex connection plugin config by combining base and plugin config.
+ * Provides a Knex connection plugin config by combining base and plugin
+ * config.
*
- * This method provides a baseConfig for a plugin database connector. If the client type
- * has not been overridden, the global connection config will be included with plugin
- * specific config as the base. Values from the plugin connection take precedence over the
- * base. Base database name is omitted for all supported databases excluding SQLite unless
- * `pluginDivisionMode` is set to `schema`.
+ * This method provides a baseConfig for a plugin database connector. If the
+ * client type has not been overridden, the global connection config will be
+ * included with plugin specific config as the base. Values from the plugin
+ * connection take precedence over the base. Base database name is omitted for
+ * all supported databases excluding SQLite unless `pluginDivisionMode` is set
+ * to `schema`.
*/
private getConnectionConfig(
pluginId: string,
@@ -249,9 +257,10 @@ export class DatabaseManager {
/**
* Provides a Knex database config for a given plugin.
*
- * This method provides a Knex configuration object along with the plugin's client type.
+ * This method provides a Knex configuration object along with the plugin's
+ * client type.
*
- * @param pluginId The plugin that the database config should correspond with
+ * @param pluginId - The plugin that the database config should correspond with
*/
private getConfigForPlugin(pluginId: string): Knex.Config {
const { client } = this.getClientType(pluginId);
@@ -264,20 +273,21 @@ export class DatabaseManager {
}
/**
- * Provides a partial Knex.Config database schema override for a given plugin.
+ * Provides a partial `Knex.Config` database schema override for a given
+ * plugin.
*
- * @param pluginId Target plugin to get database schema override
- * @returns Partial Knex.Config with database schema override
+ * @param pluginId - Target plugin to get database schema override
+ * @returns Partial `Knex.Config` with database schema override
*/
private getSchemaOverrides(pluginId: string): Knex.Config | undefined {
return createSchemaOverride(this.getClientType(pluginId).client, pluginId);
}
/**
- * Provides a partial Knex.Config database name override for a given plugin.
+ * Provides a partial `Knex.Config`• database name override for a given plugin.
*
- * @param pluginId Target plugin to get database name override
- * @returns Partial Knex.Config with database name override
+ * @param pluginId - Target plugin to get database name override
+ * @returns Partial `Knex.Config` with database name override
*/
private getDatabaseOverrides(pluginId: string): Knex.Config {
const databaseName = this.getDatabaseName(pluginId);
@@ -289,8 +299,9 @@ export class DatabaseManager {
/**
* Provides a scoped Knex client for a plugin as per application config.
*
- * @param pluginId Plugin to get a Knex client for
- * @returns Promise which resolves to a scoped Knex database client for a plugin
+ * @param pluginId - Plugin to get a Knex client for
+ * @returns Promise which resolves to a scoped Knex database client for a
+ * plugin
*/
private async getDatabase(pluginId: string): Promise {
const pluginConfig = new ConfigReader(
diff --git a/packages/backend-common/src/database/connection.ts b/packages/backend-common/src/database/connection.ts
index 3308a26573..7fc9df060d 100644
--- a/packages/backend-common/src/database/connection.ts
+++ b/packages/backend-common/src/database/connection.ts
@@ -58,7 +58,7 @@ export function createDatabaseClient(
}
/**
- * Alias for createDatabaseClient
+ * Alias for {@link createDatabaseClient}
*
* @public
* @deprecated Use createDatabaseClient instead
@@ -100,7 +100,8 @@ export async function ensureSchemaExists(
}
/**
- * Provides a Knex.Config object with the provided database name for a given client.
+ * Provides a `Knex.Config` object with the provided database name for a given
+ * client.
*/
export function createNameOverride(
client: string,
@@ -117,7 +118,8 @@ export function createNameOverride(
}
/**
- * Provides a Knex.Config object with the provided database schema for a given client. Currently only supported by `pg`.
+ * Provides a `Knex.Config` object with the provided database schema for a given
+ * client. Currently only supported by `pg`.
*/
export function createSchemaOverride(
client: string,
@@ -156,7 +158,8 @@ export function parseConnectionString(
}
/**
- * Normalizes a connection config or string into an object which can be passed to Knex.
+ * Normalizes a connection config or string into an object which can be passed
+ * to Knex.
*/
export function normalizeConnection(
connection: Knex.StaticConnectionConfig | JsonObject | string | undefined,
diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts
index 344f1088b8..2fa8b749a8 100644
--- a/packages/backend-common/src/database/types.ts
+++ b/packages/backend-common/src/database/types.ts
@@ -38,7 +38,7 @@ export interface PluginDatabaseManager {
/**
* skip database migrations. Useful if connecting to a read-only database.
*
- * @default false
+ * @defaultValue false
*/
skip?: boolean;
};
diff --git a/packages/backend-common/src/logging/formats.ts b/packages/backend-common/src/logging/formats.ts
index 0477136e63..53eb55e790 100644
--- a/packages/backend-common/src/logging/formats.ts
+++ b/packages/backend-common/src/logging/formats.ts
@@ -31,7 +31,11 @@ const coloredTemplate = (info: TransformableInfo) => {
return `${timestampColor} ${prefixColor} ${level} ${message} ${extraFields}`;
};
-/** @public */
+/**
+ * A logging format that adds coloring to console output.
+ *
+ * @public
+ */
export const coloredFormat = winston.format.combine(
winston.format.timestamp(),
winston.format.colorize({
diff --git a/packages/backend-common/src/logging/rootLogger.ts b/packages/backend-common/src/logging/rootLogger.ts
index 12db7d42a1..87180bde8f 100644
--- a/packages/backend-common/src/logging/rootLogger.ts
+++ b/packages/backend-common/src/logging/rootLogger.ts
@@ -23,12 +23,29 @@ import { escapeRegExp } from '../util/escapeRegExp';
let rootLogger: winston.Logger;
let redactionRegExp: RegExp | undefined;
-/** @public */
+/**
+ * Gets the current root logger.
+ *
+ * @public
+ */
export function getRootLogger(): winston.Logger {
return rootLogger;
}
-/** @public */
+/**
+ * Sets a completely custom default "root" logger.
+ *
+ * @remarks
+ *
+ * This is the logger instance that will be the foundation for all other logger
+ * instances passed to plugins etc, in a given backend.
+ *
+ * Only use this if you absolutely need to make a completely custom logger.
+ * Normally if you want to make light adaptations to the default logger
+ * behavior, you would instead call {@link createRootLogger}.
+ *
+ * @public
+ */
export function setRootLogger(newLogger: winston.Logger) {
rootLogger = newLogger;
}
@@ -67,7 +84,17 @@ function redactLogLine(info: winston.Logform.TransformableInfo) {
return info;
}
-/** @public */
+/**
+ * Creates a default "root" logger. This also calls {@link setRootLogger} under
+ * the hood.
+ *
+ * @remarks
+ *
+ * This is the logger instance that will be the foundation for all other logger
+ * instances passed to plugins etc, in a given backend.
+ *
+ * @public
+ */
export function createRootLogger(
options: winston.LoggerOptions = {},
env = process.env,
diff --git a/packages/backend-common/src/middleware/errorHandler.ts b/packages/backend-common/src/middleware/errorHandler.ts
index 47c9285b18..2bb46cc437 100644
--- a/packages/backend-common/src/middleware/errorHandler.ts
+++ b/packages/backend-common/src/middleware/errorHandler.ts
@@ -17,7 +17,7 @@
import {
AuthenticationError,
ConflictError,
- ErrorResponse,
+ ErrorResponseBody,
InputError,
NotAllowedError,
NotFoundError,
@@ -28,7 +28,11 @@ import { ErrorRequestHandler, NextFunction, Request, Response } from 'express';
import { Logger } from 'winston';
import { getRootLogger } from '../logging';
-/** @public */
+/**
+ * Options passed to the {@link errorHandler} middleware.
+ *
+ * @public
+ */
export type ErrorHandlerOptions = {
/**
* Whether error response bodies should show error stack traces or not.
@@ -89,7 +93,7 @@ export function errorHandler(
return;
}
- const body: ErrorResponse = {
+ const body: ErrorResponseBody = {
error: serializeError(error, { includeStack: showStackTraces }),
request: { method: req.method, url: req.url },
response: { statusCode },
diff --git a/packages/backend-common/src/middleware/statusCheckHandler.ts b/packages/backend-common/src/middleware/statusCheckHandler.ts
index a0ba59fac4..4655d610fe 100644
--- a/packages/backend-common/src/middleware/statusCheckHandler.ts
+++ b/packages/backend-common/src/middleware/statusCheckHandler.ts
@@ -16,10 +16,19 @@
import { NextFunction, Request, Response, RequestHandler } from 'express';
-/** @public */
+/**
+ * A custom status checking function, passed to {@link statusCheckHandler} and
+ * {@link createStatusCheckRouter}.
+ *
+ * @public
+ */
export type StatusCheck = () => Promise;
-/** @public */
+/**
+ * Options passed to {@link statusCheckHandler}.
+ *
+ * @public
+ */
export interface StatusCheckHandlerOptions {
/**
* Optional status function which returns a message.
diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.ts b/packages/backend-common/src/reading/AwsS3UrlReader.ts
index 1fca72e91c..e64334321d 100644
--- a/packages/backend-common/src/reading/AwsS3UrlReader.ts
+++ b/packages/backend-common/src/reading/AwsS3UrlReader.ts
@@ -94,6 +94,11 @@ const parseURL = (
};
};
+/**
+ * Implements a {@link UrlReader} for AWS S3 buckets.
+ *
+ * @public
+ */
export class AwsS3UrlReader implements UrlReader {
static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
const integrations = ScmIntegrations.fromConfig(config);
diff --git a/packages/backend-common/src/reading/AzureUrlReader.ts b/packages/backend-common/src/reading/AzureUrlReader.ts
index 37d97b8941..d6ceaec258 100644
--- a/packages/backend-common/src/reading/AzureUrlReader.ts
+++ b/packages/backend-common/src/reading/AzureUrlReader.ts
@@ -38,7 +38,11 @@ import {
ReadUrlResponse,
} from './types';
-/** @public */
+/**
+ * Implements a {@link UrlReader} for Azure repos.
+ *
+ * @public
+ */
export class AzureUrlReader implements UrlReader {
static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
const integrations = ScmIntegrations.fromConfig(config);
diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.ts b/packages/backend-common/src/reading/BitbucketUrlReader.ts
index b0e8056370..2006637545 100644
--- a/packages/backend-common/src/reading/BitbucketUrlReader.ts
+++ b/packages/backend-common/src/reading/BitbucketUrlReader.ts
@@ -41,8 +41,8 @@ import {
} from './types';
/**
- * A processor that adds the ability to read files from Bitbucket v1 and v2 APIs, such as
- * the one exposed by Bitbucket Cloud itself.
+ * Implements a {@link UrlReader} for files from Bitbucket v1 and v2 APIs, such
+ * as the one exposed by Bitbucket Cloud itself.
*
* @public
*/
diff --git a/packages/backend-common/src/reading/FetchUrlReader.ts b/packages/backend-common/src/reading/FetchUrlReader.ts
index 7090d26d35..cb873ebdf8 100644
--- a/packages/backend-common/src/reading/FetchUrlReader.ts
+++ b/packages/backend-common/src/reading/FetchUrlReader.ts
@@ -27,7 +27,7 @@ import {
import path from 'path';
/**
- * A UrlReader that does a plain fetch of the URL.
+ * A {@link UrlReader} that does a plain fetch of the URL.
*
* @public
*/
diff --git a/packages/backend-common/src/reading/GithubUrlReader.ts b/packages/backend-common/src/reading/GithubUrlReader.ts
index 6b18cfbe1a..72a8f0b90e 100644
--- a/packages/backend-common/src/reading/GithubUrlReader.ts
+++ b/packages/backend-common/src/reading/GithubUrlReader.ts
@@ -50,7 +50,7 @@ export type GhBlobResponse =
RestEndpointMethodTypes['git']['getBlob']['response']['data'];
/**
- * A processor that adds the ability to read files from GitHub v3 APIs, such as
+ * Implements a {@link UrlReader} for files through the GitHub v3 APIs, such as
* the one exposed by GitHub itself.
*
* @public
diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-common/src/reading/GitlabUrlReader.ts
index 2444e317a7..d0e43fea59 100644
--- a/packages/backend-common/src/reading/GitlabUrlReader.ts
+++ b/packages/backend-common/src/reading/GitlabUrlReader.ts
@@ -39,7 +39,11 @@ import {
} from './types';
import { trimEnd } from 'lodash';
-/** @public */
+/**
+ * Implements a {@link UrlReader} for files on GitLab.
+ *
+ * @public
+ */
export class GitlabUrlReader implements UrlReader {
static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
const integrations = ScmIntegrations.fromConfig(config);
diff --git a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts
index f1684c2945..baa9477c6a 100644
--- a/packages/backend-common/src/reading/GoogleGcsUrlReader.ts
+++ b/packages/backend-common/src/reading/GoogleGcsUrlReader.ts
@@ -48,7 +48,11 @@ const parseURL = (
};
};
-/** @public */
+/**
+ * Implements a {@link UrlReader} for files on Google GCS.
+ *
+ * @public
+ */
export class GoogleGcsUrlReader implements UrlReader {
static factory: ReaderFactory = ({ config, logger }) => {
if (!config.has('integrations.googleGcs')) {
diff --git a/packages/backend-common/src/reading/UrlReaders.ts b/packages/backend-common/src/reading/UrlReaders.ts
index a920ec080b..c0aae25808 100644
--- a/packages/backend-common/src/reading/UrlReaders.ts
+++ b/packages/backend-common/src/reading/UrlReaders.ts
@@ -27,7 +27,11 @@ import { FetchUrlReader } from './FetchUrlReader';
import { GoogleGcsUrlReader } from './GoogleGcsUrlReader';
import { AwsS3UrlReader } from './AwsS3UrlReader';
-/** @public */
+/**
+ * Creation options for {@link UrlReaders}.
+ *
+ * @public
+ */
export type UrlReadersOptions = {
/** Root config object */
config: Config;
@@ -38,13 +42,13 @@ export type UrlReadersOptions = {
};
/**
- * UrlReaders provide various utilities related to the UrlReader interface.
+ * Helps construct {@link UrlReader}s.
*
* @public
*/
export class UrlReaders {
/**
- * Creates a UrlReader without any known types.
+ * Creates a custom {@link UrlReader} wrapper for your own set of factories.
*/
static create(options: UrlReadersOptions): UrlReader {
const { logger, config, factories } = options;
@@ -65,7 +69,8 @@ export class UrlReaders {
}
/**
- * Creates a UrlReader that includes all the default factories from this package.
+ * Creates a {@link UrlReader} wrapper that includes all the default factories
+ * from this package.
*
* Any additional factories passed will be loaded before the default ones.
*/
diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts
index 46be7aa1b6..9505778705 100644
--- a/packages/backend-common/src/reading/types.ts
+++ b/packages/backend-common/src/reading/types.ts
@@ -281,7 +281,12 @@ export type FromReadableArrayOptions = Array<{
path: string;
}>;
-/** @public */
+/**
+ * A factory for response factories that handle the unpacking and inspection of
+ * complex responses such as archive data.
+ *
+ * @public
+ */
export interface ReadTreeResponseFactory {
fromTarArchive(
options: ReadTreeResponseFactoryOptions,
diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts
index 0446f08767..9cf84e9872 100644
--- a/packages/backend-common/src/scm/git.ts
+++ b/packages/backend-common/src/scm/git.ts
@@ -33,7 +33,11 @@ From : https://isomorphic-git.org/docs/en/onAuth with fix for GitHub
Azure 'notempty' token
*/
-/** @public */
+/**
+ * A convenience wrapper around the `isomorphic-git` library.
+ *
+ * @public
+ */
export class Git {
private constructor(
private readonly config: {
diff --git a/packages/backend-common/src/service/createStatusCheckRouter.ts b/packages/backend-common/src/service/createStatusCheckRouter.ts
index 0d0f93f25c..7c916da0e7 100644
--- a/packages/backend-common/src/service/createStatusCheckRouter.ts
+++ b/packages/backend-common/src/service/createStatusCheckRouter.ts
@@ -19,9 +19,26 @@ import Router from 'express-promise-router';
import express from 'express';
import { errorHandler, statusCheckHandler, StatusCheck } from '../middleware';
-/** @public */
+/**
+ * Creates a default status checking router, that you can add to your express
+ * app.
+ *
+ * @remarks
+ *
+ * This adds a `/healthcheck` route (or any other path, if given as an
+ * argument), which your infra can call to see if the service is ready to serve
+ * requests.
+ *
+ * @public
+ */
export async function createStatusCheckRouter(options: {
logger: Logger;
+ /**
+ * The path (including a leading slash) that the health check should be
+ * mounted on.
+ *
+ * @defaultValue '/healthcheck'
+ */
path?: string;
/**
* If not implemented, the default express middleware always returns 200.
diff --git a/packages/backend-common/src/service/types.ts b/packages/backend-common/src/service/types.ts
index 3e94196006..5df9f3fa5d 100644
--- a/packages/backend-common/src/service/types.ts
+++ b/packages/backend-common/src/service/types.ts
@@ -20,7 +20,11 @@ import { Router, RequestHandler, ErrorRequestHandler } from 'express';
import { Server } from 'http';
import { Logger } from 'winston';
-/** @public */
+/**
+ * A helper for building backend service instances.
+ *
+ * @public
+ */
export type ServiceBuilder = {
/**
* Sets the service parameters based on configuration.
@@ -119,5 +123,9 @@ export type ServiceBuilder = {
start(): Promise;
};
-/** @public */
+/**
+ * A factory for request loggers.
+ *
+ * @public
+ */
export type RequestLoggingHandlerFactory = (logger?: Logger) => RequestHandler;
diff --git a/packages/backend-common/src/util/ContainerRunner.ts b/packages/backend-common/src/util/ContainerRunner.ts
index be861501c3..22e40ec455 100644
--- a/packages/backend-common/src/util/ContainerRunner.ts
+++ b/packages/backend-common/src/util/ContainerRunner.ts
@@ -16,7 +16,11 @@
import { Writable } from 'stream';
-/** @public */
+/**
+ * Options passed to the {@link ContainerRunner.runContainer} method.
+ *
+ * @public
+ */
export type RunContainerOptions = {
imageName: string;
command?: string | string[];
@@ -28,7 +32,14 @@ export type RunContainerOptions = {
pullImage?: boolean;
};
-/** @public */
+/**
+ * Handles the running of containers, on behalf of others.
+ *
+ * @public
+ */
export interface ContainerRunner {
+ /**
+ * Runs a container image to completion.
+ */
runContainer(opts: RunContainerOptions): Promise;
}
diff --git a/packages/backend-common/src/util/DockerContainerRunner.ts b/packages/backend-common/src/util/DockerContainerRunner.ts
index 424913f316..522328c2ec 100644
--- a/packages/backend-common/src/util/DockerContainerRunner.ts
+++ b/packages/backend-common/src/util/DockerContainerRunner.ts
@@ -24,7 +24,11 @@ export type UserOptions = {
User?: string;
};
-/** @public */
+/**
+ * A {@link ContainerRunner} for Docker containers.
+ *
+ * @public
+ */
export class DockerContainerRunner implements ContainerRunner {
private readonly dockerClient: Docker;
diff --git a/packages/cli/config/eslint.js b/packages/cli/config/eslint.js
index 2a85c307b0..781af13577 100644
--- a/packages/cli/config/eslint.js
+++ b/packages/cli/config/eslint.js
@@ -80,6 +80,10 @@ module.exports = {
name: '@material-ui/icons',
message: "Please import '@material-ui/icons/' instead.",
},
+ {
+ name: '@material-ui/icons/', // because this is possible too ._.
+ message: "Please import '@material-ui/icons/' instead.",
+ },
...require('module').builtinModules,
],
// Avoid cross-package imports
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 3b9cf52893..e1adc8f0e2 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -51,8 +51,8 @@
"@svgr/rollup": "5.5.x",
"@svgr/webpack": "5.5.x",
"@types/webpack-env": "^1.15.2",
- "@typescript-eslint/eslint-plugin": "^v4.33.0",
- "@typescript-eslint/parser": "^v4.28.3",
+ "@typescript-eslint/eslint-plugin": "^5.9.0",
+ "@typescript-eslint/parser": "^5.9.0",
"@yarnpkg/lockfile": "^1.1.0",
"bfj": "^7.0.2",
"buffer": "^6.0.3",
@@ -61,16 +61,17 @@
"commander": "^6.1.0",
"css-loader": "^6.5.1",
"diff": "^5.0.0",
- "esbuild": "^0.14.1",
- "eslint": "^7.30.0",
+ "esbuild": "^0.14.10",
+ "esbuild-loader": "^2.18.0",
+ "eslint": "^8.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-formatter-friendly": "^7.0.0",
- "eslint-plugin-import": "^2.20.2",
- "eslint-plugin-jest": "^24.1.0",
- "eslint-plugin-jsx-a11y": "^6.2.1",
+ "eslint-plugin-import": "^2.25.4",
+ "eslint-plugin-jest": "^25.3.4",
+ "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-monorepo": "^0.3.2",
- "eslint-plugin-react": "^7.12.4",
- "eslint-plugin-react-hooks": "^4.0.0",
+ "eslint-plugin-react": "^7.28.0",
+ "eslint-plugin-react-hooks": "^4.3.0",
"express": "^4.17.1",
"fork-ts-checker-webpack-plugin": "^4.0.5",
"fs-extra": "9.1.0",
diff --git a/packages/cli/src/lib/bundler/optimization.ts b/packages/cli/src/lib/bundler/optimization.ts
index 254799f78c..a5cf38fc11 100644
--- a/packages/cli/src/lib/bundler/optimization.ts
+++ b/packages/cli/src/lib/bundler/optimization.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-import { WebpackOptionsNormalized, WebpackPluginInstance } from 'webpack';
-import TerserPlugin from 'terser-webpack-plugin';
+import { WebpackOptionsNormalized } from 'webpack';
import { BundlingOptions } from './types';
-import { isParallelDefault } from '../parallel';
+
+const { ESBuildMinifyPlugin } = require('esbuild-loader');
export const optimization = (
options: BundlingOptions,
@@ -26,16 +26,11 @@ export const optimization = (
return {
minimize: !isDev,
- // Only configure when parallel is explicitly overridden from the default
- ...(!isParallelDefault(options.parallel)
- ? {
- minimizer: [
- new TerserPlugin({
- parallel: options.parallel,
- }) as unknown as WebpackPluginInstance,
- ],
- }
- : {}),
+ minimizer: [
+ new ESBuildMinifyPlugin({
+ target: 'es2019',
+ }),
+ ],
runtimeChunk: 'single',
splitChunks: {
automaticNameDelimiter: '-',
diff --git a/packages/config/src/reader.test.ts b/packages/config/src/reader.test.ts
index 3cbab17637..c0627a200b 100644
--- a/packages/config/src/reader.test.ts
+++ b/packages/config/src/reader.test.ts
@@ -265,6 +265,19 @@ describe('ConfigReader', () => {
withLogCollector(() => config.getOptionalConfigArray('b')),
).toMatchObject({ warn: [] });
});
+
+ it('should coerce number strings to numbers', () => {
+ const config = ConfigReader.fromConfigs([
+ {
+ data: {
+ port: '123',
+ },
+ context: '1',
+ },
+ ]);
+
+ expect(config.getNumber('port')).toEqual(123);
+ });
});
describe('ConfigReader with fallback', () => {
@@ -661,16 +674,50 @@ describe('ConfigReader.get()', () => {
});
});
- it('coerces number strings to numbers', () => {
- const config = ConfigReader.fromConfigs([
- {
- data: {
- port: '123',
- },
- context: '1',
+ it('should return deep clones of the backing data', () => {
+ const data1 = {
+ foo: {
+ bar: [],
+ baz: {},
},
+ };
+ const data2 = {
+ x: {
+ y: {
+ z: {},
+ },
+ },
+ };
+
+ const reader = ConfigReader.fromConfigs([
+ { data: data1, context: '1' },
+ { data: data2, context: '2' },
]);
- expect(config.getNumber('port')).toEqual(123);
+ reader.get().foo.bar.push(1);
+ reader.get('foo').bar.push(1);
+ reader.get('foo.bar').push(1);
+ reader.get().foo.baz.x = 1;
+ reader.get('foo').baz.x = 1;
+ reader.get('foo.baz').x = 1;
+ reader.get().x.y.z.w = 1;
+ reader.get('x').y.z.w = 1;
+ reader.get('x.y').z.w = 1;
+ reader.get('x.y.z').w = 1;
+
+ const readerSingle = ConfigReader.fromConfigs([
+ { data: data1, context: '1' },
+ ]);
+
+ readerSingle.get().foo.bar.push(1);
+ readerSingle.get('foo').bar.push(1);
+ readerSingle.get('foo.bar').push(1);
+ readerSingle.get().foo.baz.x = 1;
+ readerSingle.get('foo').baz.x = 1;
+ readerSingle.get('foo.baz').x = 1;
+
+ expect(data1.foo.bar).toEqual([]);
+ expect(data1.foo.baz).toEqual({});
+ expect(data2.x.y.z).toEqual({});
});
});
diff --git a/packages/config/src/reader.ts b/packages/config/src/reader.ts
index 8c0c4140a5..129a703784 100644
--- a/packages/config/src/reader.ts
+++ b/packages/config/src/reader.ts
@@ -126,7 +126,7 @@ export class ConfigReader implements Config {
/** {@inheritdoc Config.getOptional} */
getOptional(key?: string): T | undefined {
- const value = this.readValue(key);
+ const value = cloneDeep(this.readValue(key));
const fallbackValue = this.fallback?.getOptional(key);
if (value === undefined) {
@@ -153,11 +153,8 @@ export class ConfigReader implements Config {
// Avoid merging arrays and primitive values, since that's how merging works for other
// methods for reading config.
- return mergeWith(
- {},
- { value: cloneDeep(fallbackValue) },
- { value },
- (into, from) => (!isObject(from) || !isObject(into) ? from : undefined),
+ return mergeWith({}, { value: fallbackValue }, { value }, (into, from) =>
+ !isObject(from) || !isObject(into) ? from : undefined,
).value as T;
}
diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md
index f94979f975..7a6b515255 100644
--- a/packages/core-app-api/api-report.md
+++ b/packages/core-app-api/api-report.md
@@ -50,7 +50,6 @@ import { oktaAuthApiRef } from '@backstage/core-plugin-api';
import { oneloginAuthApiRef } from '@backstage/core-plugin-api';
import { OpenIdConnectApi } from '@backstage/core-plugin-api';
import { PendingOAuthRequest } from '@backstage/core-plugin-api';
-import { PluginOutput } from '@backstage/core-plugin-api';
import { ProfileInfo } from '@backstage/core-plugin-api';
import { ProfileInfoApi } from '@backstage/core-plugin-api';
import { PropsWithChildren } from 'react';
@@ -129,21 +128,6 @@ export type ApiProviderProps = {
children: ReactNode;
};
-// @public @deprecated
-export class ApiRegistry implements ApiHolder {
- constructor(apis: Map);
- // Warning: (ae-forgotten-export) The symbol "ApiRegistryBuilder" needs to be exported by the entry point index.d.ts
- //
- // (undocumented)
- static builder(): ApiRegistryBuilder;
- // Warning: (ae-forgotten-export) The symbol "ApiImpl" needs to be exported by the entry point index.d.ts
- static from(apis: ApiImpl[]): ApiRegistry;
- // (undocumented)
- get(api: ApiRef): T | undefined;
- static with(api: ApiRef, impl: T): ApiRegistry;
- with(api: ApiRef, impl: T): ApiRegistry;
-}
-
// @public
export class ApiResolver implements ApiHolder {
constructor(factories: ApiFactoryHolder);
@@ -208,14 +192,19 @@ export type AppOptions = {
icons: AppIcons & {
[key in string]: IconComponent;
};
- plugins?: (Omit, 'output'> & {
- output(): (
- | PluginOutput
- | {
- type: string;
- }
- )[];
- })[];
+ plugins?: Array<
+ BackstagePlugin & {
+ output?(): Array<
+ | {
+ type: 'feature-flag';
+ name: string;
+ }
+ | {
+ type: string;
+ }
+ >;
+ }
+ >;
components: AppComponents;
themes: (Partial & Omit)[];
configLoader?: AppConfigLoader;
diff --git a/packages/core-app-api/src/apis/system/ApiRegistry.ts b/packages/core-app-api/src/apis/system/ApiRegistry.ts
index e433381dd1..d4990a04c5 100644
--- a/packages/core-app-api/src/apis/system/ApiRegistry.ts
+++ b/packages/core-app-api/src/apis/system/ApiRegistry.ts
@@ -18,6 +18,7 @@ import { ApiRef, ApiHolder } from '@backstage/core-plugin-api';
type ApiImpl = readonly [ApiRef, T];
+/** @internal */
class ApiRegistryBuilder {
private apis: [string, unknown][] = [];
@@ -35,8 +36,7 @@ class ApiRegistryBuilder {
/**
* A registry for utility APIs.
*
- * @public
- * @deprecated Will be removed, use {@link @backstage/test-utils#TestApiProvider} or {@link @backstage/test-utils#TestApiRegistry} instead.
+ * @internal
*/
export class ApiRegistry implements ApiHolder {
static builder() {
diff --git a/packages/core-app-api/src/apis/system/index.ts b/packages/core-app-api/src/apis/system/index.ts
index 56c42f1e2a..3c0b715249 100644
--- a/packages/core-app-api/src/apis/system/index.ts
+++ b/packages/core-app-api/src/apis/system/index.ts
@@ -16,7 +16,6 @@
export { ApiProvider } from './ApiProvider';
export type { ApiProviderProps } from './ApiProvider';
-export { ApiRegistry } from './ApiRegistry';
export { ApiResolver } from './ApiResolver';
export { ApiFactoryRegistry } from './ApiFactoryRegistry';
export type { ApiFactoryScope } from './ApiFactoryRegistry';
diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx
index 20872b26f0..b09d424737 100644
--- a/packages/core-app-api/src/app/AppManager.test.tsx
+++ b/packages/core-app-api/src/app/AppManager.test.tsx
@@ -316,7 +316,7 @@ describe('Integration Test', () => {
plugins: [
createPlugin({
id: 'test',
- register: p => p.featureFlags.register('name'),
+ featureFlags: [{ name: 'name' }],
}),
],
components,
@@ -384,8 +384,24 @@ describe('Integration Test', () => {
name: 'foo',
},
],
- register: p => p.featureFlags.register('name'),
}),
+ // We still support consuming the old feature flag API for a little while longer
+ {
+ getId() {
+ return 'old-test';
+ },
+ getApis() {
+ return [];
+ },
+ output() {
+ return [
+ {
+ type: 'feature-flag',
+ name: 'old-feature-flag',
+ },
+ ];
+ },
+ } as any,
],
components,
configLoader: async () => [],
@@ -412,12 +428,12 @@ describe('Integration Test', () => {
);
expect(storageFlags.registerFlag).toHaveBeenCalledWith({
- name: 'name',
+ name: 'foo',
pluginId: 'test',
});
expect(storageFlags.registerFlag).toHaveBeenCalledWith({
- name: 'foo',
- pluginId: 'test',
+ name: 'old-feature-flag',
+ pluginId: 'old-test',
});
});
diff --git a/packages/core-app-api/src/app/AppManager.tsx b/packages/core-app-api/src/app/AppManager.tsx
index 7cdc06a094..ef5fe43b8b 100644
--- a/packages/core-app-api/src/app/AppManager.tsx
+++ b/packages/core-app-api/src/app/AppManager.tsx
@@ -27,7 +27,6 @@ import { Route, Routes } from 'react-router-dom';
import useAsync from 'react-use/lib/useAsync';
import {
ApiProvider,
- ApiRegistry,
AppThemeSelector,
ConfigReader,
LocalStorageFeatureFlags,
@@ -80,6 +79,13 @@ import {
} from './types';
import { AppThemeProvider } from './AppThemeProvider';
import { defaultConfigLoader } from './defaultConfigLoader';
+import { ApiRegistry } from '../apis/system/ApiRegistry';
+
+type CompatiblePlugin =
+ | BackstagePlugin
+ | (Omit, 'getFeatureFlags'> & {
+ output(): Array<{ type: 'feature-flag'; name: string }>;
+ });
export function generateBoundRoutes(bindRoutes: AppOptions['bindRoutes']) {
const result = new Map();
@@ -149,7 +155,7 @@ function useConfigLoader(
if (noConfigNode) {
return {
node: (
-
+ {noConfigNode}
),
@@ -183,7 +189,7 @@ export class AppManager implements BackstageApp {
private readonly apis: Iterable;
private readonly icons: NonNullable;
- private readonly plugins: Set>;
+ private readonly plugins: Set;
private readonly components: AppComponents;
private readonly themes: AppTheme[];
private readonly configLoader?: AppConfigLoader;
@@ -196,9 +202,7 @@ export class AppManager implements BackstageApp {
constructor(options: AppOptions) {
this.apis = options.apis ?? [];
this.icons = options.icons;
- this.plugins = new Set(
- (options.plugins as BackstagePlugin[]) ?? [],
- );
+ this.plugins = new Set((options.plugins as CompatiblePlugin[]) ?? []);
this.components = options.components;
this.themes = options.themes as AppTheme[];
this.configLoader = options.configLoader ?? defaultConfigLoader;
@@ -208,7 +212,7 @@ export class AppManager implements BackstageApp {
}
getPlugins(): BackstagePlugin[] {
- return Array.from(this.plugins);
+ return Array.from(this.plugins) as BackstagePlugin[];
}
getSystemIcon(key: string): IconComponent | undefined {
@@ -282,16 +286,11 @@ export class AppManager implements BackstageApp {
}
} else {
for (const output of plugin.output()) {
- switch (output.type) {
- case 'feature-flag': {
- featureFlagsApi.registerFlag({
- name: output.name,
- pluginId: plugin.getId(),
- });
- break;
- }
- default:
- break;
+ if (output.type === 'feature-flag') {
+ featureFlagsApi.registerFlag({
+ name: output.name,
+ pluginId: plugin.getId(),
+ });
}
}
}
@@ -468,7 +467,7 @@ export class AppManager implements BackstageApp {
return this.apiHolder;
}
- private verifyPlugins(plugins: Iterable) {
+ private verifyPlugins(plugins: Iterable) {
const pluginIds = new Set();
for (const plugin of plugins) {
diff --git a/packages/core-app-api/src/app/types.ts b/packages/core-app-api/src/app/types.ts
index 4b8d2741cb..bacaf83fbd 100644
--- a/packages/core-app-api/src/app/types.ts
+++ b/packages/core-app-api/src/app/types.ts
@@ -24,7 +24,6 @@ import {
RouteRef,
SubRouteRef,
ExternalRouteRef,
- PluginOutput,
IdentityApi,
} from '@backstage/core-plugin-api';
import { AppConfig } from '@backstage/config';
@@ -232,9 +231,13 @@ export type AppOptions = {
/**
* A list of all plugins to include in the app.
*/
- plugins?: (Omit, 'output'> & {
- output(): (PluginOutput | { type: string })[];
- })[];
+ plugins?: Array<
+ BackstagePlugin & {
+ output?(): Array<
+ { type: 'feature-flag'; name: string } | { type: string }
+ >; // support for old plugins
+ }
+ >;
/**
* Supply components to the app to override the default ones.
diff --git a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx
index 68d7360400..9600a3f179 100644
--- a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx
+++ b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx
@@ -61,14 +61,14 @@ export function ResponseErrorPanel(props: ErrorPanelProps) {
);
}
- const { data, cause } = error as ResponseError;
- const { request, response } = data;
+ const { body, cause } = error as ResponseError;
+ const { request, response } = body;
const errorString = `${response.statusCode}: ${cause.name}`;
const requestString = request && `${request.method} ${request.url}`;
const messageString = cause.message.replace(/\\n/g, '\n');
const stackString = cause.stack?.replace(/\\n/g, '\n');
- const jsonString = JSON.stringify(data, undefined, 2);
+ const jsonString = JSON.stringify(body, undefined, 2);
return (
= {
getId(): string;
- output(): PluginOutput[];
getApis(): Iterable;
getFeatureFlags(): Iterable;
provide(extension: Extension): T;
@@ -446,12 +445,6 @@ export type FeatureFlag = {
pluginId: string;
};
-// @public @deprecated
-export type FeatureFlagOutput = {
- type: 'feature-flag';
- name: string;
-};
-
// @public
export interface FeatureFlagsApi {
getRegisteredFlags(): FeatureFlag[];
@@ -687,7 +680,6 @@ export type PluginConfig<
> = {
id: string;
apis?: Iterable;
- register?(hooks: PluginHooks): void;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
@@ -698,14 +690,6 @@ export type PluginFeatureFlagConfig = {
name: string;
};
-// @public @deprecated
-export type PluginHooks = {
- featureFlags: FeatureFlagsHooks;
-};
-
-// @public @deprecated
-export type PluginOutput = FeatureFlagOutput;
-
// @public
export type ProfileInfo = {
email?: string;
diff --git a/packages/core-plugin-api/src/plugin/Plugin.test.tsx b/packages/core-plugin-api/src/plugin/Plugin.test.tsx
index d3758543a1..b66235e210 100644
--- a/packages/core-plugin-api/src/plugin/Plugin.test.tsx
+++ b/packages/core-plugin-api/src/plugin/Plugin.test.tsx
@@ -28,62 +28,7 @@ describe('Plugin Feature Flag', () => {
expect(
createPlugin({
id: 'test',
- register({ featureFlags }) {
- featureFlags.register('blob');
- },
}).getFeatureFlags(),
- ).toEqual([{ name: 'blob' }]);
-
- expect(
- createPlugin({
- id: 'test',
- register({ featureFlags }) {
- featureFlags.register('blob');
- },
- featureFlags: [{ name: 'test' }],
- }).getFeatureFlags(),
- ).toEqual([{ name: 'test' }, { name: 'blob' }]);
-
- expect(
- createPlugin({
- id: 'test',
- }).getFeatureFlags(),
- ).toEqual([]);
-
- /* deprecated tests */
-
- expect(
- createPlugin({
- id: 'test',
- featureFlags: [{ name: 'test' }],
- }).output(),
- ).toEqual([{ name: 'test', type: 'feature-flag' }]);
-
- expect(
- createPlugin({
- id: 'test',
- register({ featureFlags }) {
- featureFlags.register('blob');
- },
- }).output(),
- ).toEqual([{ name: 'blob', type: 'feature-flag' }]);
- expect(
- createPlugin({
- id: 'test',
- register({ featureFlags }) {
- featureFlags.register('blob');
- },
- featureFlags: [{ name: 'test' }],
- }).output(),
- ).toEqual([
- { name: 'test', type: 'feature-flag' },
- { name: 'blob', type: 'feature-flag' },
- ]);
-
- expect(
- createPlugin({
- id: 'test',
- }).output(),
).toEqual([]);
});
});
diff --git a/packages/core-plugin-api/src/plugin/Plugin.tsx b/packages/core-plugin-api/src/plugin/Plugin.tsx
index 0fb7574cd7..d97554b27b 100644
--- a/packages/core-plugin-api/src/plugin/Plugin.tsx
+++ b/packages/core-plugin-api/src/plugin/Plugin.tsx
@@ -16,7 +16,6 @@
import {
PluginConfig,
- PluginOutput,
BackstagePlugin,
Extension,
AnyRoutes,
@@ -33,8 +32,6 @@ export class PluginImpl<
ExternalRoutes extends AnyExternalRoutes,
> implements BackstagePlugin
{
- private storedOutput?: PluginOutput[];
-
constructor(private readonly config: PluginConfig) {}
getId(): string {
@@ -46,11 +43,7 @@ export class PluginImpl<
}
getFeatureFlags(): Iterable {
- const registeredFlags = this.output()
- .filter(({ type }) => type === 'feature-flag')
- .map(({ name }) => ({ name }));
-
- return registeredFlags;
+ return this.config.featureFlags?.slice() ?? [];
}
get routes(): Routes {
@@ -61,34 +54,6 @@ export class PluginImpl<
return this.config.externalRoutes ?? ({} as ExternalRoutes);
}
- output(): PluginOutput[] {
- if (this.storedOutput) {
- return this.storedOutput;
- }
- const outputs = new Array();
- this.storedOutput = outputs;
-
- if (this.config.featureFlags) {
- for (const flag of this.config.featureFlags) {
- outputs.push({ type: 'feature-flag', name: flag.name });
- }
- }
-
- if (!this.config.register) {
- return outputs;
- }
-
- this.config.register({
- featureFlags: {
- register(name) {
- outputs.push({ type: 'feature-flag', name });
- },
- },
- });
-
- return this.storedOutput;
- }
-
provide(extension: Extension): T {
return extension.expose(this);
}
diff --git a/packages/core-plugin-api/src/plugin/index.ts b/packages/core-plugin-api/src/plugin/index.ts
index 4f7609fd9c..95f5a6b219 100644
--- a/packages/core-plugin-api/src/plugin/index.ts
+++ b/packages/core-plugin-api/src/plugin/index.ts
@@ -20,10 +20,7 @@ export type {
AnyRoutes,
BackstagePlugin,
Extension,
- FeatureFlagOutput,
FeatureFlagsHooks,
PluginConfig,
- PluginHooks,
- PluginOutput,
PluginFeatureFlagConfig,
} from './types';
diff --git a/packages/core-plugin-api/src/plugin/types.ts b/packages/core-plugin-api/src/plugin/types.ts
index 0f8d3404d8..d639327838 100644
--- a/packages/core-plugin-api/src/plugin/types.ts
+++ b/packages/core-plugin-api/src/plugin/types.ts
@@ -17,24 +17,6 @@
import { RouteRef, SubRouteRef, ExternalRouteRef } from '../routing';
import { AnyApiFactory } from '../apis/system';
-/**
- * Replace with using {@link RouteRef}s.
- * @deprecated will be removed
- * @public
- */
-export type FeatureFlagOutput = {
- type: 'feature-flag';
- name: string;
-};
-
-/**
- * {@link FeatureFlagOutput} type.
- *
- * @public
- * @deprecated Use {@link BackstagePlugin.getFeatureFlags} instead.
- */
-export type PluginOutput = FeatureFlagOutput;
-
/**
* Plugin extension type.
*
@@ -72,10 +54,6 @@ export type BackstagePlugin<
ExternalRoutes extends AnyExternalRoutes = {},
> = {
getId(): string;
- /**
- * @deprecated use getFeatureFlags instead.
- * */
- output(): PluginOutput[];
getApis(): Iterable;
/**
* Returns all registered feature flags for this plugin.
@@ -107,23 +85,11 @@ export type PluginConfig<
> = {
id: string;
apis?: Iterable;
- /** @deprecated use featureFlags property instead for defining feature flags */
- register?(hooks: PluginHooks): void;
routes?: Routes;
externalRoutes?: ExternalRoutes;
featureFlags?: PluginFeatureFlagConfig[];
};
-/**
- * Holds hooks registered by the plugin.
- *
- * @deprecated - feature flags are now registered in plugin config under featureFlags
- * @public
- */
-export type PluginHooks = {
- featureFlags: FeatureFlagsHooks;
-};
-
/**
* Interface for registering feature flags hooks.
*
diff --git a/packages/create-app/package.json b/packages/create-app/package.json
index e95dbb3a9d..639e0370d7 100644
--- a/packages/create-app/package.json
+++ b/packages/create-app/package.json
@@ -67,6 +67,8 @@
"@backstage/plugin-explore": "*",
"@backstage/plugin-github-actions": "*",
"@backstage/plugin-lighthouse": "*",
+ "@backstage/plugin-permission-common": "*",
+ "@backstage/plugin-permission-node": "*",
"@backstage/plugin-proxy-backend": "*",
"@backstage/plugin-rollbar-backend": "*",
"@backstage/plugin-scaffolder": "*",
diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts
index 3765422923..f89ff7f391 100644
--- a/packages/create-app/src/lib/versions.ts
+++ b/packages/create-app/src/lib/versions.ts
@@ -57,6 +57,8 @@ import { version as pluginExplore } from '../../../../plugins/explore/package.js
import { version as pluginGithubActions } from '../../../../plugins/github-actions/package.json';
import { version as pluginLighthouse } from '../../../../plugins/lighthouse/package.json';
import { version as pluginOrg } from '../../../../plugins/org/package.json';
+import { version as pluginPermissionCommon } from '../../../../plugins/permission-common/package.json';
+import { version as pluginPermissionNode } from '../../../../plugins/permission-node/package.json';
import { version as pluginProxyBackend } from '../../../../plugins/proxy-backend/package.json';
import { version as pluginRollbarBackend } from '../../../../plugins/rollbar-backend/package.json';
import { version as pluginScaffolder } from '../../../../plugins/scaffolder/package.json';
@@ -94,6 +96,8 @@ export const packageVersions = {
'@backstage/plugin-github-actions': pluginGithubActions,
'@backstage/plugin-lighthouse': pluginLighthouse,
'@backstage/plugin-org': pluginOrg,
+ '@backstage/plugin-permission-common': pluginPermissionCommon,
+ '@backstage/plugin-permission-node': pluginPermissionNode,
'@backstage/plugin-proxy-backend': pluginProxyBackend,
'@backstage/plugin-rollbar-backend': pluginRollbarBackend,
'@backstage/plugin-scaffolder': pluginScaffolder,
diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs
index a2ee89c546..96dc724a1e 100644
--- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs
+++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs
@@ -23,6 +23,8 @@
"@backstage/plugin-app-backend": "^{{version '@backstage/plugin-app-backend'}}",
"@backstage/plugin-auth-backend": "^{{version '@backstage/plugin-auth-backend'}}",
"@backstage/plugin-catalog-backend": "^{{version '@backstage/plugin-catalog-backend'}}",
+ "@backstage/plugin-permission-common": "^{{version '@backstage/plugin-permission-common'}}",
+ "@backstage/plugin-permission-node": "^{{version '@backstage/plugin-permission-node'}}",
"@backstage/plugin-proxy-backend": "^{{version '@backstage/plugin-proxy-backend'}}",
"@backstage/plugin-scaffolder-backend": "^{{version '@backstage/plugin-scaffolder-backend'}}",
"@backstage/plugin-search-backend": "^{{version '@backstage/plugin-search-backend'}}",
diff --git a/packages/create-app/templates/default-app/packages/backend/src/index.ts b/packages/create-app/templates/default-app/packages/backend/src/index.ts
index 08d21e61f7..70bc66bcdd 100644
--- a/packages/create-app/templates/default-app/packages/backend/src/index.ts
+++ b/packages/create-app/templates/default-app/packages/backend/src/index.ts
@@ -29,6 +29,7 @@ import proxy from './plugins/proxy';
import techdocs from './plugins/techdocs';
import search from './plugins/search';
import { PluginEnvironment } from './types';
+import { ServerPermissionClient } from '@backstage/plugin-permission-node';
function makeCreateEnv(config: Config) {
const root = getRootLogger();
@@ -38,6 +39,10 @@ function makeCreateEnv(config: Config) {
const databaseManager = DatabaseManager.fromConfig(config);
const tokenManager = ServerTokenManager.noop();
const taskScheduler = TaskScheduler.fromConfig(config);
+ const permissions = ServerPermissionClient.fromConfig(config, {
+ discovery,
+ tokenManager,
+ });
root.info(`Created UrlReader ${reader}`);
@@ -55,6 +60,7 @@ function makeCreateEnv(config: Config) {
discovery,
tokenManager,
scheduler,
+ permissions,
};
};
}
diff --git a/packages/create-app/templates/default-app/packages/backend/src/types.ts b/packages/create-app/templates/default-app/packages/backend/src/types.ts
index c3d0158dc6..0862b0e874 100644
--- a/packages/create-app/templates/default-app/packages/backend/src/types.ts
+++ b/packages/create-app/templates/default-app/packages/backend/src/types.ts
@@ -8,6 +8,7 @@ import {
UrlReader,
} from '@backstage/backend-common';
import { PluginTaskScheduler } from '@backstage/backend-tasks';
+import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
export type PluginEnvironment = {
logger: Logger;
@@ -18,4 +19,5 @@ export type PluginEnvironment = {
discovery: PluginEndpointDiscovery;
tokenManager: TokenManager;
scheduler: PluginTaskScheduler;
+ permissions: PermissionAuthorizer;
};
diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md
index 97b011bad6..a01581135b 100644
--- a/packages/errors/api-report.md
+++ b/packages/errors/api-report.md
@@ -33,9 +33,6 @@ export type ErrorLike = {
[unknownKeys: string]: unknown;
};
-// @public @deprecated
-export type ErrorResponse = ErrorResponseBody;
-
// @public
export type ErrorResponseBody = {
error: SerializedError;
@@ -68,9 +65,6 @@ export class NotFoundError extends CustomErrorBase {}
// @public
export class NotModifiedError extends CustomErrorBase {}
-// @public @deprecated
-export function parseErrorResponse(response: Response): Promise;
-
// @public
export function parseErrorResponseBody(
response: Response,
@@ -78,17 +72,8 @@ export function parseErrorResponseBody(
// @public
export class ResponseError extends Error {
- // @deprecated
- constructor(props: {
- message: string;
- response: Response;
- data: ErrorResponseBody;
- cause: Error;
- });
readonly body: ErrorResponseBody;
readonly cause: Error;
- // @deprecated
- get data(): ErrorResponseBody;
static fromResponse(response: Response): Promise;
readonly response: Response;
}
diff --git a/packages/errors/src/errors/ResponseError.test.ts b/packages/errors/src/errors/ResponseError.test.ts
index 52a308dbb8..94f2e850d9 100644
--- a/packages/errors/src/errors/ResponseError.test.ts
+++ b/packages/errors/src/errors/ResponseError.test.ts
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-import { ErrorResponse } from '../serialization';
+import { ErrorResponseBody } from '../serialization';
import { ResponseError } from './ResponseError';
describe('ResponseError', () => {
it('constructs itself from a response', async () => {
- const body: ErrorResponse = {
+ const body: ErrorResponseBody = {
error: { name: 'Fours', message: 'Expected fives', stack: 'lines' },
request: { method: 'GET', url: '/' },
response: { statusCode: 444 },
diff --git a/packages/errors/src/errors/ResponseError.ts b/packages/errors/src/errors/ResponseError.ts
index a20035cd8c..84c8137bb5 100644
--- a/packages/errors/src/errors/ResponseError.ts
+++ b/packages/errors/src/errors/ResponseError.ts
@@ -75,10 +75,7 @@ export class ResponseError extends Error {
});
}
- /**
- * @deprecated will be removed.
- **/
- constructor(props: {
+ private constructor(props: {
message: string;
response: Response;
data: ErrorResponseBody;
@@ -90,13 +87,4 @@ export class ResponseError extends Error {
this.body = props.data;
this.cause = props.cause;
}
- /**
- * The parsed JSON error body, as sent by the server.
- * @deprecated use body instead.
- */
- get data(): ErrorResponseBody {
- // eslint-disable-next-line no-console
- console.warn('ErrorResponse.data is deprecated, use .body instead.');
- return this.body;
- }
}
diff --git a/packages/errors/src/serialization/index.ts b/packages/errors/src/serialization/index.ts
index b86661d496..b03514f749 100644
--- a/packages/errors/src/serialization/index.ts
+++ b/packages/errors/src/serialization/index.ts
@@ -16,5 +16,5 @@
export { deserializeError, serializeError, stringifyError } from './error';
export type { SerializedError } from './error';
-export { parseErrorResponse, parseErrorResponseBody } from './response';
-export type { ErrorResponse, ErrorResponseBody } from './response';
+export { parseErrorResponseBody } from './response';
+export type { ErrorResponseBody } from './response';
diff --git a/packages/errors/src/serialization/response.ts b/packages/errors/src/serialization/response.ts
index 4a1731646d..3580220525 100644
--- a/packages/errors/src/serialization/response.ts
+++ b/packages/errors/src/serialization/response.ts
@@ -16,14 +16,6 @@
import { SerializedError } from './error';
-/**
- * A standard shape of JSON data returned as the body of backend errors.
- *
- * @public
- * @deprecated - Use {@link ErrorResponseBody} instead.
- */
-export type ErrorResponse = ErrorResponseBody;
-
/**
* A standard shape of JSON data returned as the body of backend errors.
*
@@ -48,25 +40,6 @@ export type ErrorResponseBody = {
};
};
-/**
- * Attempts to construct an ErrorResponse out of a failed server request.
- * Assumes that the response has already been checked to be not ok. This
- * function consumes the body of the response, and assumes that it hasn't
- * been consumed before.
- *
- * The code is forgiving, and constructs a useful synthetic body as best it can
- * if the response body wasn't on the expected form.
- *
- * @public
- * @param response - The response of a failed request
- * @deprecated - Use {@link parseErrorResponseBody} instead.
- */
-export async function parseErrorResponse(
- response: Response,
-): Promise {
- return parseErrorResponseBody(response);
-}
-
/**
* Attempts to construct an ErrorResponseBody out of a failed server request.
* Assumes that the response has already been checked to be not ok. This
diff --git a/packages/storybook/.storybook/main.js b/packages/storybook/.storybook/main.js
index f5852b0164..6e0a2b92fa 100644
--- a/packages/storybook/.storybook/main.js
+++ b/packages/storybook/.storybook/main.js
@@ -8,6 +8,7 @@ const BACKSTAGE_CORE_STORIES = [
'packages/core-components',
'plugins/org',
'plugins/search',
+ 'plugins/home',
];
module.exports = ({ args }) => {
diff --git a/packages/storybook/package.json b/packages/storybook/package.json
index 5df0c06632..a0e9b25d76 100644
--- a/packages/storybook/package.json
+++ b/packages/storybook/package.json
@@ -9,6 +9,9 @@
},
"dependencies": {
"@backstage/theme": "^0.2.0",
+ "@backstage/test-utils": "^0.2.1",
+ "@backstage/core-app-api": "^0.3.1",
+ "@backstage/core-plugin-api": "^0.4.1",
"react": "^16.13.1",
"react-dom": "^16.13.1"
},
diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md
index a75a6d958e..6a3813e49f 100644
--- a/packages/test-utils/api-report.md
+++ b/packages/test-utils/api-report.md
@@ -8,10 +8,13 @@ import { AnalyticsEvent } from '@backstage/core-plugin-api';
import { ApiHolder } from '@backstage/core-plugin-api';
import { ApiRef } from '@backstage/core-plugin-api';
import { ComponentType } from 'react';
+import { Config } from '@backstage/config';
+import { ConfigApi } from '@backstage/core-plugin-api';
import { ErrorApi } from '@backstage/core-plugin-api';
import { ErrorApiError } from '@backstage/core-plugin-api';
import { ErrorApiErrorContext } from '@backstage/core-plugin-api';
import { ExternalRouteRef } from '@backstage/core-plugin-api';
+import { JsonObject } from '@backstage/types';
import { JsonValue } from '@backstage/types';
import { Observable } from '@backstage/types';
import { ReactElement } from 'react';
@@ -52,6 +55,43 @@ export class MockAnalyticsApi implements AnalyticsApi {
// @public
export function mockBreakpoint(options: { matches: boolean }): void;
+// @public
+export class MockConfigApi implements ConfigApi {
+ constructor(data: JsonObject);
+ // (undocumented)
+ get(key?: string): T;
+ // (undocumented)
+ getBoolean(key: string): boolean;
+ // (undocumented)
+ getConfig(key: string): Config;
+ // (undocumented)
+ getConfigArray(key: string): Config[];
+ // (undocumented)
+ getNumber(key: string): number;
+ // (undocumented)
+ getOptional(key?: string): T | undefined;
+ // (undocumented)
+ getOptionalBoolean(key: string): boolean | undefined;
+ // (undocumented)
+ getOptionalConfig(key: string): Config | undefined;
+ // (undocumented)
+ getOptionalConfigArray(key: string): Config[] | undefined;
+ // (undocumented)
+ getOptionalNumber(key: string): number | undefined;
+ // (undocumented)
+ getOptionalString(key: string): string | undefined;
+ // (undocumented)
+ getOptionalStringArray(key: string): string[] | undefined;
+ // (undocumented)
+ getString(key: string): string;
+ // (undocumented)
+ getStringArray(key: string): string[];
+ // (undocumented)
+ has(key: string): boolean;
+ // (undocumented)
+ keys(): string[];
+}
+
// @public
export class MockErrorApi implements ErrorApi {
constructor(options?: MockErrorApiOptions);
diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json
index acfe03bf99..48745f7068 100644
--- a/packages/test-utils/package.json
+++ b/packages/test-utils/package.json
@@ -29,6 +29,7 @@
"clean": "backstage-cli clean"
},
"dependencies": {
+ "@backstage/config": "^0.1.11",
"@backstage/core-app-api": "^0.3.0",
"@backstage/core-plugin-api": "^0.4.0",
"@backstage/theme": "^0.2.14",
diff --git a/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.test.ts b/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.test.ts
new file mode 100644
index 0000000000..972733d44d
--- /dev/null
+++ b/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.test.ts
@@ -0,0 +1,42 @@
+/*
+ * 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 { MockConfigApi } from './MockConfigApi';
+
+describe('MockConfigApi', () => {
+ it('is able to read some basic config', () => {
+ const mock = new MockConfigApi({
+ app: {
+ title: 'Hello',
+ },
+ x: 1,
+ y: false,
+ z: [{ a: 3 }],
+ });
+
+ expect(mock.getString('app.title')).toEqual('Hello');
+ expect(mock.getNumber('x')).toEqual(1);
+ expect(mock.getBoolean('y')).toEqual(false);
+ expect(mock.getConfigArray('z')[0].getOptionalNumber('a')).toEqual(3);
+
+ expect(() => mock.getString('x')).toThrow(
+ "Invalid type in config for key 'x' in 'mock-config', got number, wanted string",
+ );
+ expect(() => mock.getString('missing')).toThrow(
+ "Missing required config value at 'missing'",
+ );
+ });
+});
diff --git a/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.ts b/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.ts
new file mode 100644
index 0000000000..372c295c02
--- /dev/null
+++ b/packages/test-utils/src/testUtils/apis/ConfigApi/MockConfigApi.ts
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Config, ConfigReader } from '@backstage/config';
+import { JsonObject, JsonValue } from '@backstage/types';
+import { ConfigApi } from '@backstage/core-plugin-api';
+
+/**
+ * MockConfigApi is a thin wrapper around {@link @backstage/config#ConfigReader}
+ * that can be used to mock configuration using a plain object.
+ *
+ * @public
+ * @example
+ * ```tsx
+ * const mockConfig = new MockConfigApi({
+ * app: { baseUrl: 'https://example.com' },
+ * });
+ *
+ * const rendered = await renderInTestApp(
+ *
+ *
+ * ,
+ * );
+ * ```
+ */
+export class MockConfigApi implements ConfigApi {
+ private readonly config: ConfigReader;
+
+ // NOTE: not extending in order to avoid inheriting the static `.fromConfigs`
+ constructor(data: JsonObject) {
+ this.config = new ConfigReader(data);
+ }
+
+ /** {@inheritdoc @backstage/config#Config.has} */
+ has(key: string): boolean {
+ return this.config.has(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.keys} */
+ keys(): string[] {
+ return this.config.keys();
+ }
+ /** {@inheritdoc @backstage/config#Config.get} */
+ get(key?: string): T {
+ return this.config.get(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptional} */
+ getOptional(key?: string): T | undefined {
+ return this.config.getOptional(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getConfig} */
+ getConfig(key: string): Config {
+ return this.config.getConfig(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalConfig} */
+ getOptionalConfig(key: string): Config | undefined {
+ return this.config.getOptionalConfig(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getConfigArray} */
+ getConfigArray(key: string): Config[] {
+ return this.config.getConfigArray(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalConfigArray} */
+ getOptionalConfigArray(key: string): Config[] | undefined {
+ return this.config.getOptionalConfigArray(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getNumber} */
+ getNumber(key: string): number {
+ return this.config.getNumber(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalNumber} */
+ getOptionalNumber(key: string): number | undefined {
+ return this.config.getOptionalNumber(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getBoolean} */
+ getBoolean(key: string): boolean {
+ return this.config.getBoolean(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalBoolean} */
+ getOptionalBoolean(key: string): boolean | undefined {
+ return this.config.getOptionalBoolean(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getString} */
+ getString(key: string): string {
+ return this.config.getString(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalString} */
+ getOptionalString(key: string): string | undefined {
+ return this.config.getOptionalString(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getStringArray} */
+ getStringArray(key: string): string[] {
+ return this.config.getStringArray(key);
+ }
+ /** {@inheritdoc @backstage/config#Config.getOptionalStringArray} */
+ getOptionalStringArray(key: string): string[] | undefined {
+ return this.config.getOptionalStringArray(key);
+ }
+}
diff --git a/packages/test-utils/src/testUtils/apis/ConfigApi/index.ts b/packages/test-utils/src/testUtils/apis/ConfigApi/index.ts
new file mode 100644
index 0000000000..6418899f79
--- /dev/null
+++ b/packages/test-utils/src/testUtils/apis/ConfigApi/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2022 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { MockConfigApi } from './MockConfigApi';
diff --git a/packages/test-utils/src/testUtils/apis/index.ts b/packages/test-utils/src/testUtils/apis/index.ts
index 44b423a264..8f6bb06f9e 100644
--- a/packages/test-utils/src/testUtils/apis/index.ts
+++ b/packages/test-utils/src/testUtils/apis/index.ts
@@ -15,5 +15,6 @@
*/
export * from './AnalyticsApi';
+export * from './ConfigApi';
export * from './ErrorApi';
export * from './StorageApi';
diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json
index 71dbcf9f02..3afd6cefe3 100644
--- a/plugins/auth-backend/package.json
+++ b/plugins/auth-backend/package.json
@@ -35,7 +35,6 @@
"@backstage/catalog-model": "^0.9.8",
"@backstage/config": "^0.1.11",
"@backstage/errors": "^0.1.5",
- "@backstage/test-utils": "^0.2.1",
"@backstage/types": "^0.1.1",
"@google-cloud/firestore": "^4.15.1",
"@types/express": "^4.17.6",
@@ -75,6 +74,7 @@
},
"devDependencies": {
"@backstage/cli": "^0.10.5",
+ "@backstage/test-utils": "^0.2.1",
"@types/body-parser": "^1.19.0",
"@types/cookie-parser": "^1.4.2",
"@types/express-session": "^1.17.2",
diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md
index bbf92944b9..e2dbef74e5 100644
--- a/plugins/catalog-backend-module-ldap/api-report.md
+++ b/plugins/catalog-backend-module-ldap/api-report.md
@@ -17,26 +17,26 @@ import { SearchEntry } from 'ldapjs';
import { SearchOptions } from 'ldapjs';
import { UserEntity } from '@backstage/catalog-model';
-// Warning: (ae-missing-release-tag) "defaultGroupTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type BindConfig = {
+ dn: string;
+ secret: string;
+};
+
+// @public
export function defaultGroupTransformer(
vendor: LdapVendor,
config: GroupConfig,
entry: SearchEntry,
): Promise;
-// Warning: (ae-missing-release-tag) "defaultUserTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function defaultUserTransformer(
vendor: LdapVendor,
config: UserConfig,
entry: SearchEntry,
): Promise;
-// Warning: (ae-missing-release-tag) "GroupConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type GroupConfig = {
dn: string;
@@ -57,12 +57,6 @@ export type GroupConfig = {
};
};
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-undefined-tag) The TSDoc tag "@return" is not defined in this configuration
-// Warning: (ae-missing-release-tag) "GroupTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type GroupTransformer = (
vendor: LdapVendor,
@@ -70,28 +64,18 @@ export type GroupTransformer = (
group: SearchEntry,
) => Promise;
-// Warning: (ae-missing-release-tag) "LDAP_DN_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const LDAP_DN_ANNOTATION = 'backstage.io/ldap-dn';
-// Warning: (ae-missing-release-tag) "LDAP_RDN_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const LDAP_RDN_ANNOTATION = 'backstage.io/ldap-rdn';
-// Warning: (ae-missing-release-tag) "LDAP_UUID_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const LDAP_UUID_ANNOTATION = 'backstage.io/ldap-uuid';
-// Warning: (ae-missing-release-tag) "LdapClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class LdapClient {
constructor(client: Client, logger: Logger_2);
- // Warning: (ae-forgotten-export) The symbol "BindConfig" needs to be exported by the entry point index.d.ts
- //
// (undocumented)
static create(
logger: Logger_2,
@@ -100,22 +84,14 @@ export class LdapClient {
): Promise;
getRootDSE(): Promise;
getVendor(): Promise;
- // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
- // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
search(dn: string, options: SearchOptions): Promise;
- // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
- // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
- // Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
- // Warning: (ae-forgotten-export) The symbol "SearchCallback" needs to be exported by the entry point index.d.ts
searchStreaming(
dn: string,
options: SearchOptions,
- f: SearchCallback,
+ f: (entry: SearchEntry) => void,
): Promise;
}
-// Warning: (ae-missing-release-tag) "LdapOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class LdapOrgEntityProvider implements EntityProvider {
constructor(options: {
@@ -140,12 +116,9 @@ export class LdapOrgEntityProvider implements EntityProvider {
): LdapOrgEntityProvider;
// (undocumented)
getProviderName(): string;
- // (undocumented)
read(): Promise;
}
-// Warning: (ae-missing-release-tag) "LdapOrgReaderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class LdapOrgReaderProcessor implements CatalogProcessor {
constructor(options: {
@@ -171,8 +144,6 @@ export class LdapOrgReaderProcessor implements CatalogProcessor {
): Promise;
}
-// Warning: (ae-missing-release-tag) "LdapProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type LdapProviderConfig = {
target: string;
@@ -181,8 +152,6 @@ export type LdapProviderConfig = {
groups: GroupConfig;
};
-// Warning: (ae-missing-release-tag) "LdapVendor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type LdapVendor = {
dnAttributeName: string;
@@ -190,12 +159,6 @@ export type LdapVendor = {
decodeStringAttribute: (entry: SearchEntry, name: string) => string[];
};
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (ae-missing-release-tag) "mapStringAttr" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export function mapStringAttr(
entry: SearchEntry,
@@ -204,18 +167,9 @@ export function mapStringAttr(
setter: (value: string) => void,
): void;
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (ae-missing-release-tag) "readLdapConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export function readLdapConfig(config: Config): LdapProviderConfig[];
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (ae-missing-release-tag) "readLdapOrg" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export function readLdapOrg(
client: LdapClient,
@@ -231,8 +185,6 @@ export function readLdapOrg(
groups: GroupEntity[];
}>;
-// Warning: (ae-missing-release-tag) "UserConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type UserConfig = {
dn: string;
@@ -251,21 +203,10 @@ export type UserConfig = {
};
};
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// Warning: (tsdoc-undefined-tag) The TSDoc tag "@return" is not defined in this configuration
-// Warning: (ae-missing-release-tag) "UserTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type UserTransformer = (
vendor: LdapVendor,
config: UserConfig,
user: SearchEntry,
) => Promise;
-
-// Warnings were encountered during analysis:
-//
-// src/ldap/vendors.d.ts:17:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
-// src/ldap/vendors.d.ts:18:8 - (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
```
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts
index 553081f4b0..ea13ba49ee 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts
@@ -25,14 +25,12 @@ import {
LdapVendor,
} from './vendors';
-export interface SearchCallback {
- (entry: SearchEntry): void;
-}
-
/**
- * Basic wrapper for the ldapjs library.
+ * Basic wrapper for the `ldapjs` library.
*
* Helps out with promisifying calls, paging, binding etc.
+ *
+ * @public
*/
export class LdapClient {
private vendor: Promise | undefined;
@@ -75,8 +73,8 @@ export class LdapClient {
/**
* Performs an LDAP search operation.
*
- * @param dn The fully qualified base DN to search within
- * @param options The search options
+ * @param dn - The fully qualified base DN to search within
+ * @param options - The search options
*/
async search(dn: string, options: SearchOptions): Promise {
try {
@@ -128,14 +126,14 @@ export class LdapClient {
/**
* Performs an LDAP search operation, calls a function on each entry to limit memory usage
*
- * @param dn The fully qualified base DN to search within
- * @param options The search options
- * @param f The callback to call on each search entry
+ * @param dn - The fully qualified base DN to search within
+ * @param options - The search options
+ * @param f - The callback to call on each search entry
*/
async searchStreaming(
dn: string,
options: SearchOptions,
- f: SearchCallback,
+ f: (entry: SearchEntry) => void,
): Promise {
try {
return await new Promise((resolve, reject) => {
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
index 9fb536a87f..06ac24d3ae 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
@@ -209,4 +209,88 @@ describe('readLdapConfig', () => {
const expected = '(|(cn=foo bar)(cn=bar))';
expect(actual[0].users.options.filter).toEqual(expected);
});
+
+ it('supports a dot nested set structure', () => {
+ const config = {
+ providers: [
+ {
+ target: 'target',
+ users: {
+ dn: 'udn',
+ options: {
+ filter: 'f',
+ },
+ set: {
+ 'metadata.annotations': {
+ a: 'b',
+ },
+ },
+ },
+ groups: {
+ dn: 'gdn',
+ options: {
+ filter: 'f',
+ },
+ set: {
+ x: { a: 'b' },
+ },
+ },
+ },
+ ],
+ };
+ const actual = readLdapConfig(new ConfigReader(config));
+
+ expect(actual[0].users.set).toEqual({ 'metadata.annotations': { a: 'b' } });
+ });
+
+ it('throws on attempts to modify the set structure', () => {
+ const config = {
+ providers: [
+ {
+ target: 'target',
+ users: {
+ dn: 'udn',
+ options: {
+ filter: 'f',
+ },
+ set: {
+ x: { a: 'b' },
+ },
+ },
+ groups: {
+ dn: 'gdn',
+ options: {
+ filter: 'f',
+ },
+ set: {
+ x: { a: 'b' },
+ },
+ },
+ },
+ ],
+ };
+ const actual = readLdapConfig(new ConfigReader(config));
+
+ expect(() => {
+ (actual[0].users.set as any).y = 2;
+ }).toThrowErrorMatchingInlineSnapshot(
+ `"Cannot add property y, object is not extensible"`,
+ );
+ expect(() => {
+ (actual[0].users.set as any).x.b = 2;
+ }).toThrowErrorMatchingInlineSnapshot(
+ `"Cannot add property b, object is not extensible"`,
+ );
+
+ expect(() => {
+ (actual[0].groups.set as any).y = 2;
+ }).toThrowErrorMatchingInlineSnapshot(
+ `"Cannot add property y, object is not extensible"`,
+ );
+ expect(() => {
+ (actual[0].groups.set as any).x.b = 2;
+ }).toThrowErrorMatchingInlineSnapshot(
+ `"Cannot add property b, object is not extensible"`,
+ );
+ });
});
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.ts
index dc1ec4910d..526467962e 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/config.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/config.ts
@@ -23,6 +23,8 @@ import { trimEnd } from 'lodash';
/**
* The configuration parameters for a single LDAP provider.
+ *
+ * @public
*/
export type LdapProviderConfig = {
// The prefix of the target that this matches on, e.g.
@@ -39,6 +41,8 @@ export type LdapProviderConfig = {
/**
* The settings to use for the a command.
+ *
+ * @public
*/
export type BindConfig = {
// The DN of the user to auth as, e.g.
@@ -50,6 +54,8 @@ export type BindConfig = {
/**
* The settings that govern the reading and interpretation of users.
+ *
+ * @public
*/
export type UserConfig = {
// The DN under which users are stored.
@@ -88,6 +94,8 @@ export type UserConfig = {
/**
* The settings that govern the reading and interpretation of groups.
+ *
+ * @public
*/
export type GroupConfig = {
// The DN under which groups are stored.
@@ -163,9 +171,20 @@ const defaultConfig = {
/**
* Parses configuration.
*
- * @param config The root of the LDAP config hierarchy
+ * @param config - The root of the LDAP config hierarchy
+ *
+ * @public
*/
export function readLdapConfig(config: Config): LdapProviderConfig[] {
+ function freeze(data: T): T {
+ return JSON.parse(JSON.stringify(data), (_key, value) => {
+ if (typeof value === 'object' && value !== null) {
+ Object.freeze(value);
+ }
+ return value;
+ });
+ }
+
function readBindConfig(
c: Config | undefined,
): LdapProviderConfig['bind'] | undefined {
@@ -217,7 +236,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] {
if (!c) {
return undefined;
}
- return Object.fromEntries(c.keys().map(path => [path, c.get(path)]));
+ return c.get();
}
function readUserMapConfig(
@@ -297,6 +316,6 @@ export function readLdapConfig(config: Config): LdapProviderConfig[] {
// Replace arrays instead of merging, otherwise default behavior
return Array.isArray(from) ? from : undefined;
});
- return merged as LdapProviderConfig;
+ return freeze(merged) as LdapProviderConfig;
});
}
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/constants.ts b/plugins/catalog-backend-module-ldap/src/ldap/constants.ts
index 73df5d6de8..cdc448b4dd 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/constants.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/constants.ts
@@ -22,6 +22,8 @@
* example, for an item with the fully qualified DN
* uid=john,ou=people,ou=spotify,dc=spotify,dc=net the generated entity would
* have this annotation, with the value "john".
+ *
+ * @public
*/
export const LDAP_RDN_ANNOTATION = 'backstage.io/ldap-rdn';
@@ -33,6 +35,8 @@ export const LDAP_RDN_ANNOTATION = 'backstage.io/ldap-rdn';
* for an item with the DN uid=john,ou=people,ou=spotify,dc=spotify,dc=net the
* generated entity would have this annotation, with that full string as its
* value.
+ *
+ * @public
*/
export const LDAP_DN_ANNOTATION = 'backstage.io/ldap-dn';
@@ -44,5 +48,7 @@ export const LDAP_DN_ANNOTATION = 'backstage.io/ldap-dn';
* for an item with the UUID 76ef928a-b251-1037-9840-d78227f36a7e, the
* generated entity would have this annotation, with that full string as its
* value.
+ *
+ * @public
*/
export const LDAP_UUID_ANNOTATION = 'backstage.io/ldap-uuid';
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/index.ts b/plugins/catalog-backend-module-ldap/src/ldap/index.ts
index 70500299ae..c3aace492f 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/index.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/index.ts
@@ -17,7 +17,12 @@
export { LdapClient } from './client';
export { mapStringAttr } from './util';
export { readLdapConfig } from './config';
-export type { LdapProviderConfig, GroupConfig, UserConfig } from './config';
+export type {
+ LdapProviderConfig,
+ GroupConfig,
+ UserConfig,
+ BindConfig,
+} from './config';
export type { LdapVendor } from './vendors';
export {
LDAP_DN_ANNOTATION,
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts
index c4f203c5db..875ffb7029 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/read.test.ts
@@ -25,7 +25,13 @@ import {
LDAP_RDN_ANNOTATION,
LDAP_UUID_ANNOTATION,
} from './constants';
-import { readLdapGroups, readLdapUsers, resolveRelations } from './read';
+import {
+ defaultGroupTransformer,
+ defaultUserTransformer,
+ readLdapGroups,
+ readLdapUsers,
+ resolveRelations,
+} from './read';
import { ActiveDirectoryVendor, DefaultLdapVendor } from './vendors';
function user(data: RecursivePartial): UserEntity {
@@ -264,6 +270,7 @@ describe('readLdapGroups', () => {
new Map([['dn-value', new Set(['x', 'y', 'z'])]]),
);
});
+
it('transfers all attributes from Microsoft Active Directory', async () => {
client.getVendor.mockResolvedValue(ActiveDirectoryVendor);
client.searchStreaming.mockImplementation(async (_dn, _opts, fn) => {
@@ -358,6 +365,7 @@ describe('resolveRelations', () => {
expect(parent.spec.children).toEqual(['child']);
expect(child.spec.parent).toEqual('parent');
});
+
it('matches by UUID', () => {
const parent = group({
metadata: {
@@ -539,3 +547,162 @@ describe('resolveRelations', () => {
});
});
});
+
+describe('defaultUserTransformer', () => {
+ it('can set things safely', async () => {
+ const config: UserConfig = {
+ dn: 'ddd',
+ options: {},
+ map: {
+ rdn: 'uid',
+ name: 'uid',
+ displayName: 'cn',
+ email: 'mail',
+ memberOf: 'memberOf',
+ },
+ set: {
+ 'metadata.annotations.a': 1,
+ 'metadata.annotations': { a: 2, b: 3 },
+ },
+ };
+
+ const entry = searchEntry({
+ uid: ['uid-value'],
+ description: ['description-value'],
+ cn: ['cn-value'],
+ mail: ['mail-value'],
+ avatarUrl: ['avatarUrl-value'],
+ memberOf: ['x', 'y', 'z'],
+ entryDN: ['dn-value'],
+ entryUUID: ['uuid-value'],
+ });
+
+ let output = await defaultUserTransformer(DefaultLdapVendor, config, entry);
+ expect(output).toEqual({
+ apiVersion: 'backstage.io/v1beta1',
+ kind: 'User',
+ metadata: {
+ annotations: {
+ 'backstage.io/ldap-dn': 'dn-value',
+ 'backstage.io/ldap-rdn': 'uid-value',
+ 'backstage.io/ldap-uuid': 'uuid-value',
+ a: 2,
+ b: 3,
+ },
+ name: 'uid-value',
+ },
+ spec: {
+ memberOf: [],
+ profile: { displayName: 'cn-value', email: 'mail-value' },
+ },
+ });
+
+ (output!.metadata.annotations as any).c = 7;
+
+ // exact same inputs again
+ output = await defaultUserTransformer(DefaultLdapVendor, config, entry);
+ expect(output).toEqual({
+ apiVersion: 'backstage.io/v1beta1',
+ kind: 'User',
+ metadata: {
+ annotations: {
+ 'backstage.io/ldap-dn': 'dn-value',
+ 'backstage.io/ldap-rdn': 'uid-value',
+ 'backstage.io/ldap-uuid': 'uuid-value',
+ a: 2,
+ b: 3,
+ },
+ name: 'uid-value',
+ },
+ spec: {
+ memberOf: [],
+ profile: { displayName: 'cn-value', email: 'mail-value' },
+ },
+ });
+ });
+});
+
+describe('defaultGroupTransformer', () => {
+ it('can set things safely', async () => {
+ const config: GroupConfig = {
+ dn: 'ddd',
+ options: {},
+ map: {
+ rdn: 'uid',
+ name: 'uid',
+ displayName: 'cn',
+ email: 'mail',
+ description: 'description',
+ type: 'type',
+ members: 'members',
+ memberOf: 'memberOf',
+ },
+ set: {
+ 'metadata.annotations.a': 1,
+ 'metadata.annotations': { a: 2, b: 3 },
+ },
+ };
+
+ const entry = searchEntry({
+ uid: ['uid-value'],
+ description: ['description-value'],
+ cn: ['cn-value'],
+ mail: ['mail-value'],
+ avatarUrl: ['avatarUrl-value'],
+ memberOf: ['x', 'y', 'z'],
+ entryDN: ['dn-value'],
+ entryUUID: ['uuid-value'],
+ });
+
+ let output = await defaultGroupTransformer(
+ DefaultLdapVendor,
+ config,
+ entry,
+ );
+ expect(output).toEqual({
+ apiVersion: 'backstage.io/v1beta1',
+ kind: 'Group',
+ metadata: {
+ annotations: {
+ 'backstage.io/ldap-dn': 'dn-value',
+ 'backstage.io/ldap-rdn': 'uid-value',
+ 'backstage.io/ldap-uuid': 'uuid-value',
+ a: 2,
+ b: 3,
+ },
+ description: 'description-value',
+ name: 'uid-value',
+ },
+ spec: {
+ type: 'unknown',
+ children: [],
+ profile: { displayName: 'cn-value', email: 'mail-value' },
+ },
+ });
+
+ (output!.metadata.annotations as any).c = 7;
+
+ // exact same inputs again
+ output = await defaultGroupTransformer(DefaultLdapVendor, config, entry);
+ expect(output).toEqual({
+ apiVersion: 'backstage.io/v1beta1',
+ kind: 'Group',
+ metadata: {
+ annotations: {
+ 'backstage.io/ldap-dn': 'dn-value',
+ 'backstage.io/ldap-rdn': 'uid-value',
+ 'backstage.io/ldap-uuid': 'uuid-value',
+ a: 2,
+ b: 3,
+ },
+ description: 'description-value',
+ name: 'uid-value',
+ },
+ spec: {
+ type: 'unknown',
+ children: [],
+ profile: { displayName: 'cn-value', email: 'mail-value' },
+ },
+ });
+ });
+});
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts
index 2d6e3c1608..e15ec85554 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts
@@ -17,6 +17,7 @@
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { SearchEntry } from 'ldapjs';
import lodashSet from 'lodash/set';
+import cloneDeep from 'lodash/cloneDeep';
import { buildOrgHierarchy } from './org';
import { LdapClient } from './client';
import { GroupConfig, UserConfig } from './config';
@@ -30,6 +31,12 @@ import { Logger } from 'winston';
import { GroupTransformer, UserTransformer } from './types';
import { mapStringAttr } from './util';
+/**
+ * The default implementation of the transformation from an LDAP entry to a
+ * User entity.
+ *
+ * @public
+ */
export async function defaultUserTransformer(
vendor: LdapVendor,
config: UserConfig,
@@ -52,7 +59,7 @@ export async function defaultUserTransformer(
if (set) {
for (const [path, value] of Object.entries(set)) {
- lodashSet(entity, path, value);
+ lodashSet(entity, path, cloneDeep(value));
}
}
@@ -87,9 +94,9 @@ export async function defaultUserTransformer(
/**
* Reads users out of an LDAP provider.
*
- * @param client The LDAP client
- * @param config The user data configuration
- * @param opts
+ * @param client - The LDAP client
+ * @param config - The user data configuration
+ * @param opts - Additional options
*/
export async function readLdapUsers(
client: LdapClient,
@@ -124,6 +131,12 @@ export async function readLdapUsers(
return { users: entities, userMemberOf };
}
+/**
+ * The default implementation of the transformation from an LDAP entry to a
+ * Group entity.
+ *
+ * @public
+ */
export async function defaultGroupTransformer(
vendor: LdapVendor,
config: GroupConfig,
@@ -146,7 +159,7 @@ export async function defaultGroupTransformer(
if (set) {
for (const [path, value] of Object.entries(set)) {
- lodashSet(entity, path, value);
+ lodashSet(entity, path, cloneDeep(value));
}
}
@@ -184,9 +197,9 @@ export async function defaultGroupTransformer(
/**
* Reads groups out of an LDAP provider.
*
- * @param client The LDAP client
- * @param config The group data configuration
- * @param opts
+ * @param client - The LDAP client
+ * @param config - The group data configuration
+ * @param opts - Additional options
*/
export async function readLdapGroups(
client: LdapClient,
@@ -239,13 +252,12 @@ export async function readLdapGroups(
/**
* Reads users and groups out of an LDAP provider.
*
- * Invokes the above "raw" read functions and stitches together the results
- * with all relations etc filled in.
+ * @param client - The LDAP client
+ * @param userConfig - The user data configuration
+ * @param groupConfig - The group data configuration
+ * @param options - Additional options
*
- * @param client The LDAP client
- * @param userConfig The user data configuration
- * @param groupConfig The group data configuration
- * @param options
+ * @public
*/
export async function readLdapOrg(
client: LdapClient,
@@ -260,6 +272,9 @@ export async function readLdapOrg(
users: UserEntity[];
groups: GroupEntity[];
}> {
+ // Invokes the above "raw" read functions and stitches together the results
+ // with all relations etc filled in.
+
const { users, userMemberOf } = await readLdapUsers(client, userConfig, {
transformer: options?.userTransformer,
});
@@ -320,14 +335,14 @@ function ensureItems(
* Takes groups and entities with empty relations, and fills in the various
* relations that were returned by the readers, and forms the org hierarchy.
*
- * @param groups Group entities with empty relations; modified in place
- * @param users User entities with empty relations; modified in place
- * @param userMemberOf For a user DN, the set of group DNs or UUIDs that the
- * user is a member of
- * @param groupMemberOf For a group DN, the set of group DNs or UUIDs that the
- * group is a member of (parents in the hierarchy)
- * @param groupMember For a group DN, the set of group DNs or UUIDs that are
- * members of the group (children in the hierarchy)
+ * @param groups - Group entities with empty relations; modified in place
+ * @param users - User entities with empty relations; modified in place
+ * @param userMemberOf - For a user DN, the set of group DNs or UUIDs that the
+ * user is a member of
+ * @param groupMemberOf - For a group DN, the set of group DNs or UUIDs that
+ * the group is a member of (parents in the hierarchy)
+ * @param groupMember - For a group DN, the set of group DNs or UUIDs that are
+ * members of the group (children in the hierarchy)
*/
export function resolveRelations(
groups: GroupEntity[],
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/types.ts b/plugins/catalog-backend-module-ldap/src/ldap/types.ts
index e32e4c5b42..9d7c326add 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/types.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/types.ts
@@ -21,10 +21,15 @@ import { GroupConfig, UserConfig } from './config';
/**
* Customize the ingested User entity
*
- * @param vendor The LDAP vendor that can be used to find and decode vendor specific attributes
- * @param config The User specific config used by the default transformer.
- * @param user The found LDAP entry in its source format. This is the entry that you want to transform
- * @return A `UserEntity` or `undefined` if you want to ignore the found user for being ingested by the catalog
+ * @param vendor - The LDAP vendor that can be used to find and decode vendor
+ * specific attributes
+ * @param config - The User specific config used by the default transformer.
+ * @param user - The found LDAP entry in its source format. This is the entry
+ * that you want to transform
+ * @returns A `UserEntity` or `undefined` if you want to ignore the found user
+ * for being ingested by the catalog
+ *
+ * @public
*/
export type UserTransformer = (
vendor: LdapVendor,
@@ -35,10 +40,15 @@ export type UserTransformer = (
/**
* Customize the ingested Group entity
*
- * @param vendor The LDAP vendor that can be used to find and decode vendor specific attributes
- * @param config The Group specific config used by the default transformer.
- * @param group The found LDAP entry in its source format. This is the entry that you want to transform
- * @return A `GroupEntity` or `undefined` if you want to ignore the found group for being ingested by the catalog
+ * @param vendor - The LDAP vendor that can be used to find and decode vendor
+ * specific attributes
+ * @param config - The Group specific config used by the default transformer.
+ * @param group - The found LDAP entry in its source format. This is the entry
+ * that you want to transform
+ * @returns A `GroupEntity` or `undefined` if you want to ignore the found group
+ * for being ingested by the catalog
+ *
+ * @public
*/
export type GroupTransformer = (
vendor: LdapVendor,
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/util.ts b/plugins/catalog-backend-module-ldap/src/ldap/util.ts
index 21ee40f52c..21829cef35 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/util.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/util.ts
@@ -20,19 +20,25 @@ import { LdapVendor } from './vendors';
/**
* Builds a string form of an LDAP Error structure.
*
- * @param error The error
+ * @param error - The error
*/
export function errorString(error: LDAPError) {
return `${error.code} ${error.name}: ${error.message}`;
}
/**
- * Maps a single-valued attribute to a consumer
+ * Maps a single-valued attribute to a consumer.
*
- * @param entry The LDAP source entry
- * @param vendor The LDAP vendor
- * @param attributeName The source attribute to map. If the attribute is undefined the mapping will be silently ignored.
- * @param setter The function to be called with the decoded attribute from the source entry
+ * This helper can be useful when implementing a user or group transformer.
+ *
+ * @param entry - The LDAP source entry
+ * @param vendor - The LDAP vendor
+ * @param attributeName - The source attribute to map. If the attribute is
+ * undefined the mapping will be silently ignored.
+ * @param setter - The function to be called with the decoded attribute from the
+ * source entry
+ *
+ * @public
*/
export function mapStringAttr(
entry: SearchEntry,
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts
index 3341497ca8..3df29a5fb9 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/vendors.ts
@@ -18,6 +18,8 @@ import { SearchEntry } from 'ldapjs';
/**
* An LDAP Vendor handles unique nuances between different vendors.
+ *
+ * @public
*/
export type LdapVendor = {
/**
@@ -31,8 +33,8 @@ export type LdapVendor = {
/**
* Decode ldap entry values for a given attribute name to their string representation.
*
- * @param entry The ldap entry
- * @param name The attribute to decode
+ * @param entry - The ldap entry
+ * @param name - The attribute to decode
*/
decodeStringAttribute: (entry: SearchEntry, name: string) => string[];
};
diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
index c0cd663052..c74e5b3aee 100644
--- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
+++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
@@ -39,6 +39,13 @@ import {
/**
* Reads user and group entries out of an LDAP service, and provides them as
* User and Group entities for the catalog.
+ *
+ * @remarks
+ *
+ * Add an instance of this class to your catalog builder, and then periodically
+ * call the {@link LdapOrgEntityProvider.read} method.
+ *
+ * @public
*/
export class LdapOrgEntityProvider implements EntityProvider {
private connection?: EntityProviderConnection;
@@ -113,14 +120,20 @@ export class LdapOrgEntityProvider implements EntityProvider {
},
) {}
+ /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */
getProviderName() {
return `LdapOrgEntityProvider:${this.options.id}`;
}
+ /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */
async connect(connection: EntityProviderConnection) {
this.connection = connection;
}
+ /**
+ * Runs one complete ingestion loop. Call this method regularly at some
+ * appropriate cadence.
+ */
async read() {
if (!this.connection) {
throw new Error('Not initialized');
diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts
index f87afc38b9..be2d748840 100644
--- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts
+++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts
@@ -33,6 +33,8 @@ import {
/**
* Extracts teams and users out of an LDAP server.
+ *
+ * @public
*/
export class LdapOrgReaderProcessor implements CatalogProcessor {
private readonly providers: LdapProviderConfig[];
diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md
index e1a837d0c1..662056eff1 100644
--- a/plugins/catalog-backend-module-msgraph/api-report.md
+++ b/plugins/catalog-backend-module-msgraph/api-report.md
@@ -16,51 +16,37 @@ import * as msal from '@azure/msal-node';
import { Response as Response_2 } from 'node-fetch';
import { UserEntity } from '@backstage/catalog-model';
-// Warning: (ae-missing-release-tag) "defaultGroupTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function defaultGroupTransformer(
group: MicrosoftGraph.Group,
groupPhoto?: string,
): Promise;
-// Warning: (ae-missing-release-tag) "defaultOrganizationTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function defaultOrganizationTransformer(
organization: MicrosoftGraph.Organization,
): Promise;
-// Warning: (ae-missing-release-tag) "defaultUserTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function defaultUserTransformer(
user: MicrosoftGraph.User,
userPhoto?: string,
): Promise;
-// Warning: (ae-missing-release-tag) "GroupTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export type GroupTransformer = (
group: MicrosoftGraph.Group,
groupPhoto?: string,
) => Promise;
-// Warning: (ae-missing-release-tag) "MICROSOFT_GRAPH_GROUP_ID_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const MICROSOFT_GRAPH_GROUP_ID_ANNOTATION =
'graph.microsoft.com/group-id';
-// Warning: (ae-missing-release-tag) "MICROSOFT_GRAPH_TENANT_ID_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const MICROSOFT_GRAPH_TENANT_ID_ANNOTATION =
'graph.microsoft.com/tenant-id';
-// Warning: (ae-missing-release-tag) "MICROSOFT_GRAPH_USER_ID_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id';
@@ -76,7 +62,6 @@ export class MicrosoftGraphClient {
groupId: string,
maxSize: number,
): Promise;
- // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-msgraph" does not have an export "ODataQuery"
getGroups(query?: ODataQuery): AsyncIterable;
getOrganization(tenantId: string): Promise;
// (undocumented)
@@ -86,18 +71,12 @@ export class MicrosoftGraphClient {
maxSize: number,
): Promise;
getUserProfile(userId: string): Promise;
- // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-msgraph" does not have an export "ODataQuery"
getUsers(query?: ODataQuery): AsyncIterable;
- // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-msgraph" does not have an export "ODataQuery"
requestApi(path: string, query?: ODataQuery): Promise;
- // Warning: (ae-forgotten-export) The symbol "ODataQuery" needs to be exported by the entry point index.d.ts
- // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/plugin-catalog-backend-module-msgraph" does not have an export "ODataQuery"
requestCollection(path: string, query?: ODataQuery): AsyncIterable;
requestRaw(url: string): Promise;
}
-// Warning: (ae-missing-release-tag) "MicrosoftGraphOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class MicrosoftGraphOrgEntityProvider implements EntityProvider {
constructor(options: {
@@ -124,12 +103,9 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider {
): MicrosoftGraphOrgEntityProvider;
// (undocumented)
getProviderName(): string;
- // (undocumented)
read(): Promise;
}
-// Warning: (ae-missing-release-tag) "MicrosoftGraphOrgReaderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {
constructor(options: {
@@ -157,8 +133,6 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {
): Promise;
}
-// Warning: (ae-missing-release-tag) "MicrosoftGraphProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export type MicrosoftGraphProviderConfig = {
target: string;
@@ -171,28 +145,27 @@ export type MicrosoftGraphProviderConfig = {
groupFilter?: string;
};
-// Warning: (ae-missing-release-tag) "normalizeEntityName" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function normalizeEntityName(name: string): string;
-// Warning: (ae-missing-release-tag) "OrganizationTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
+export type ODataQuery = {
+ filter?: string;
+ expand?: string[];
+ select?: string[];
+};
+
+// @public
export type OrganizationTransformer = (
organization: MicrosoftGraph.Organization,
) => Promise;
-// Warning: (ae-missing-release-tag) "readMicrosoftGraphConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function readMicrosoftGraphConfig(
config: Config,
): MicrosoftGraphProviderConfig[];
-// Warning: (ae-missing-release-tag) "readMicrosoftGraphOrg" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export function readMicrosoftGraphOrg(
client: MicrosoftGraphClient,
tenantId: string,
@@ -210,15 +183,9 @@ export function readMicrosoftGraphOrg(
groups: GroupEntity[];
}>;
-// Warning: (ae-missing-release-tag) "UserTransformer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
+// @public
export type UserTransformer = (
user: MicrosoftGraph.User,
userPhoto?: string,
) => Promise;
-
-// Warnings were encountered during analysis:
-//
-// src/microsoftGraph/config.d.ts:28:8 - (tsdoc-undefined-tag) The TSDoc tag "@visibility" is not defined in this configuration
```
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts
index 63f256afbd..827c9fc14d 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/client.ts
@@ -41,6 +41,11 @@ export type ODataQuery = {
select?: string[];
};
+/**
+ * Extends the base msgraph types to include the odata type.
+ *
+ * @public
+ */
export type GroupMember =
| (MicrosoftGraph.Group & { '@odata.type': '#microsoft.graph.user' })
| (MicrosoftGraph.User & { '@odata.type': '#microsoft.graph.group' });
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts
index 91a6d49b57..4d37e24632 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts
@@ -19,6 +19,8 @@ import { trimEnd } from 'lodash';
/**
* The configuration parameters for a single Microsoft Graph provider.
+ *
+ * @public
*/
export type MicrosoftGraphProviderConfig = {
/**
@@ -42,8 +44,6 @@ export type MicrosoftGraphProviderConfig = {
clientId: string;
/**
* The OAuth client secret to use for authenticating requests.
- *
- * @visibility secret
*/
clientSecret: string;
/**
@@ -66,6 +66,13 @@ export type MicrosoftGraphProviderConfig = {
groupFilter?: string;
};
+/**
+ * Parses configuration.
+ *
+ * @param config - The root of the msgraph config hierarchy
+ *
+ * @public
+ */
export function readMicrosoftGraphConfig(
config: Config,
): MicrosoftGraphProviderConfig[] {
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/constants.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/constants.ts
index e6abbebb0a..bbfbd61efe 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/constants.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/constants.ts
@@ -16,17 +16,23 @@
/**
* The tenant id used by the Microsoft Graph API
+ *
+ * @public
*/
export const MICROSOFT_GRAPH_TENANT_ID_ANNOTATION =
'graph.microsoft.com/tenant-id';
/**
* The group id used by the Microsoft Graph API
+ *
+ * @public
*/
export const MICROSOFT_GRAPH_GROUP_ID_ANNOTATION =
'graph.microsoft.com/group-id';
/**
* The user id used by the Microsoft Graph API
+ *
+ * @public
*/
export const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id';
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/helper.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/helper.ts
index 41dbc1aed8..fd09d754d4 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/helper.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/helper.ts
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+/**
+ * Takes an input string and cleans it up to become suitable as an entity name.
+ *
+ * @public
+ */
export function normalizeEntityName(name: string): string {
let cleaned = name
.trim()
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts
index eeb436d317..b0d53b43a2 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/index.ts
@@ -14,6 +14,7 @@
* limitations under the License.
*/
export { MicrosoftGraphClient } from './client';
+export type { ODataQuery } from './client';
export { readMicrosoftGraphConfig } from './config';
export type { MicrosoftGraphProviderConfig } from './config';
export {
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts
index 7dd6f83e2e..b2845ac78d 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import {
GroupEntity,
stringifyEntityRef,
@@ -35,6 +36,12 @@ import {
UserTransformer,
} from './types';
+/**
+ * The default implementation of the transformation from a graph user entry to
+ * a User entity.
+ *
+ * @public
+ */
export async function defaultUserTransformer(
user: MicrosoftGraph.User,
userPhoto?: string,
@@ -208,6 +215,12 @@ export async function readMicrosoftGraphUsersInGroups(
return { users };
}
+/**
+ * The default implementation of the transformation from a graph organization
+ * entry to a Group entity.
+ *
+ * @public
+ */
export async function defaultOrganizationTransformer(
organization: MicrosoftGraph.Organization,
): Promise {
@@ -258,6 +271,12 @@ function extractGroupName(group: MicrosoftGraph.Group): string {
return (group.mailNickname || group.displayName) as string;
}
+/**
+ * The default implementation of the transformation from a graph group entry to
+ * a Group entity.
+ *
+ * @public
+ */
export async function defaultGroupTransformer(
group: MicrosoftGraph.Group,
groupPhoto?: string,
@@ -472,6 +491,11 @@ export function resolveRelations(
buildMemberOf(groups, users);
}
+/**
+ * Reads an entire org as Group and User entities.
+ *
+ * @public
+ */
export async function readMicrosoftGraphOrg(
client: MicrosoftGraphClient,
tenantId: string,
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/types.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/types.ts
index fab662cc3f..ef60d7b018 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/types.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/types.ts
@@ -17,15 +17,30 @@
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
+/**
+ * Customize the ingested User entity
+ *
+ * @public
+ */
export type UserTransformer = (
user: MicrosoftGraph.User,
userPhoto?: string,
) => Promise;
+/**
+ * Customize the ingested organization Group entity
+ *
+ * @public
+ */
export type OrganizationTransformer = (
organization: MicrosoftGraph.Organization,
) => Promise;
+/**
+ * Customize the ingested Group entity
+ *
+ * @public
+ */
export type GroupTransformer = (
group: MicrosoftGraph.Group,
groupPhoto?: string,
diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts
index ea396162dd..6d66723970 100644
--- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts
+++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import {
Entity,
LOCATION_ANNOTATION,
@@ -41,6 +42,8 @@ import {
/**
* Reads user and group entries out of Microsoft Graph, and provides them as
* User and Group entities for the catalog.
+ *
+ * @public
*/
export class MicrosoftGraphOrgEntityProvider implements EntityProvider {
private connection?: EntityProviderConnection;
@@ -91,14 +94,20 @@ export class MicrosoftGraphOrgEntityProvider implements EntityProvider {
},
) {}
+ /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */
getProviderName() {
return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;
}
+ /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */
async connect(connection: EntityProviderConnection) {
this.connection = connection;
}
+ /**
+ * Runs one complete ingestion loop. Call this method regularly at some
+ * appropriate cadence.
+ */
async read() {
if (!this.connection) {
throw new Error('Not initialized');
diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts
index cb7729e04a..351a4983d9 100644
--- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts
+++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts
@@ -34,6 +34,8 @@ import {
/**
* Extracts teams and users out of a the Microsoft Graph API.
+ *
+ * @public
*/
export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {
private readonly providers: MicrosoftGraphProviderConfig[];
diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md
index f773905ca0..4b4036ee8a 100644
--- a/plugins/catalog-backend/api-report.md
+++ b/plugins/catalog-backend/api-report.md
@@ -25,6 +25,8 @@ import { Location as Location_2 } from '@backstage/catalog-model';
import { LocationSpec } from '@backstage/catalog-model';
import { Logger as Logger_2 } from 'winston';
import { Organizations } from 'aws-sdk';
+import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
+import { PermissionRule } from '@backstage/plugin-permission-node';
import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
import { ResourceEntityV1alpha1 } from '@backstage/catalog-model';
@@ -301,6 +303,7 @@ export type CatalogEnvironment = {
database: PluginDatabaseManager;
config: Config;
reader: UrlReader;
+ permissions: PermissionAuthorizer;
};
// Warning: (ae-missing-release-tag) "CatalogProcessingEngine" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -519,6 +522,11 @@ export class CommonDatabase implements Database {
): Promise;
}
+// @public
+export const createCatalogPermissionRule: (
+ rule: PermissionRule,
+) => PermissionRule;
+
// Warning: (ae-missing-release-tag) "CreateDatabaseOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public @deprecated (undocumented)
@@ -1302,6 +1310,13 @@ export class NextCatalogBuilder {
addEntityPolicy(...policies: EntityPolicy[]): NextCatalogBuilder;
// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
addEntityProvider(...providers: EntityProvider[]): NextCatalogBuilder;
+ addPermissionRules(
+ ...permissionRules: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ unknown[]
+ >[]
+ ): void;
// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
addProcessor(...processors: CatalogProcessor[]): NextCatalogBuilder;
build(): Promise<{
@@ -1349,6 +1364,8 @@ export interface NextRouterOptions {
// (undocumented)
logger: Logger_2;
// (undocumented)
+ permissionRules?: PermissionRule[];
+ // (undocumented)
refreshService?: RefreshService;
}
@@ -1380,6 +1397,32 @@ export function parseEntityYaml(
location: LocationSpec,
): Iterable;
+// @public
+export const permissionRules: {
+ hasAnnotation: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ [annotation: string]
+ >;
+ hasLabel: PermissionRule;
+ hasMetadata: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ [key: string, value?: string | undefined]
+ >;
+ hasSpec: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ [key: string, value?: string | undefined]
+ >;
+ isEntityKind: PermissionRule;
+ isEntityOwner: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ [claims: string[]]
+ >;
+};
+
// Warning: (ae-missing-release-tag) "PlaceholderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
@@ -1473,6 +1516,7 @@ export type RefreshIntervalFunction = () => number;
// @public
export type RefreshOptions = {
entityRef: string;
+ authorizationToken?: string;
};
// @public
diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json
index 01e79314c5..504e86a736 100644
--- a/plugins/catalog-backend/package.json
+++ b/plugins/catalog-backend/package.json
@@ -36,6 +36,9 @@
"@backstage/config": "^0.1.11",
"@backstage/errors": "^0.1.5",
"@backstage/integration": "^0.7.0",
+ "@backstage/plugin-catalog-common": "^0.1.0",
+ "@backstage/plugin-permission-common": "^0.3.0",
+ "@backstage/plugin-permission-node": "^0.2.3",
"@backstage/search-common": "^0.2.1",
"@backstage/types": "^0.1.1",
"@octokit/graphql": "^4.5.8",
@@ -64,6 +67,7 @@
"devDependencies": {
"@backstage/backend-test-utils": "^0.1.12",
"@backstage/cli": "^0.10.4",
+ "@backstage/plugin-permission-common": "^0.3.0",
"@backstage/test-utils": "^0.2.1",
"@types/core-js": "^2.5.4",
"@types/git-url-parse": "^9.0.0",
diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts
index 7ad888bee4..43bbc19730 100644
--- a/plugins/catalog-backend/src/index.ts
+++ b/plugins/catalog-backend/src/index.ts
@@ -28,3 +28,4 @@ export * from './util';
export * from './processing';
export * from './providers';
export * from './service';
+export * from './permissions';
diff --git a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts
index 926aa67635..728d35ea3d 100644
--- a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts
+++ b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts
@@ -14,7 +14,12 @@
* limitations under the License.
*/
-import { getVoidLogger, UrlReader } from '@backstage/backend-common';
+import {
+ getVoidLogger,
+ PluginEndpointDiscovery,
+ ServerTokenManager,
+ UrlReader,
+} from '@backstage/backend-common';
import { Entity } from '@backstage/catalog-model';
import { ConfigReader } from '@backstage/config';
import { Knex } from 'knex';
@@ -24,6 +29,7 @@ import { CatalogProcessorParser } from '../../ingestion';
import * as result from '../../ingestion/processors/results';
import { CatalogBuilder } from './CatalogBuilder';
import { CatalogEnvironment } from '../../service';
+import { ServerPermissionClient } from '@backstage/plugin-permission-node';
const dummyEntity = {
apiVersion: 'backstage.io/v1alpha1',
@@ -47,11 +53,25 @@ describe('CatalogBuilder', () => {
readTree: jest.fn(),
search: jest.fn(),
};
+ const config = new ConfigReader({});
+ const mockBaseUrl = 'http://backstage:9191/i-am-a-mock-base';
+ const discovery: PluginEndpointDiscovery = {
+ async getBaseUrl() {
+ return mockBaseUrl;
+ },
+ async getExternalBaseUrl() {
+ return mockBaseUrl;
+ },
+ };
const env: CatalogEnvironment = {
logger: getVoidLogger(),
database: { getClient: async () => db },
- config: new ConfigReader({}),
+ config,
reader,
+ permissions: ServerPermissionClient.fromConfig(config, {
+ discovery,
+ tokenManager: ServerTokenManager.noop(),
+ }),
};
beforeEach(async () => {
diff --git a/plugins/catalog-backend/src/permissions/index.ts b/plugins/catalog-backend/src/permissions/index.ts
new file mode 100644
index 0000000000..624d6dd7ac
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export * from './rules';
diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts
new file mode 100644
index 0000000000..80c86cf250
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.test.ts
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { createPropertyRule } from './createPropertyRule';
+
+describe('createPropertyRule', () => {
+ const { name, description, apply, toQuery } = createPropertyRule('metadata');
+
+ it('formats the rule name correctly', () => {
+ expect(name).toBe('HAS_METADATA');
+ });
+
+ it('formats the rule description correctly', () => {
+ expect(description).toBe(
+ 'Allow entities which have the specified metadata subfield.',
+ );
+ });
+
+ describe('apply', () => {
+ describe('key only', () => {
+ it('returns false when specified key is not present', () => {
+ expect(
+ apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ },
+ },
+ 'org.name',
+ ),
+ ).toBe(false);
+ });
+
+ it('returns true when specified key is present', () => {
+ expect(
+ apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ org: {
+ name: 'test-org',
+ },
+ },
+ },
+ 'org.name',
+ ),
+ ).toBe(true);
+ });
+ });
+
+ describe('key and value', () => {
+ it('returns false when specified key is not present', () => {
+ expect(
+ apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ },
+ },
+ 'org.name',
+ 'test-org',
+ ),
+ ).toBe(false);
+ });
+
+ it('returns false when specified value is not present', () => {
+ expect(
+ apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ org: {
+ name: 'another-org',
+ },
+ },
+ },
+ 'org.name',
+ 'test-org',
+ ),
+ ).toBe(false);
+ });
+
+ it('returns true when specified key and value is present', () => {
+ expect(
+ apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ org: {
+ name: 'test-org',
+ },
+ },
+ },
+ 'org.name',
+ 'test-org',
+ ),
+ ).toBe(true);
+ });
+ });
+ });
+
+ describe('toQuery', () => {
+ it('returns an appropriate catalog-backend filter', () => {
+ expect(toQuery('backstage.io/test-component')).toEqual({
+ key: 'metadata.backstage.io/test-component',
+ });
+ });
+ });
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts
new file mode 100644
index 0000000000..27a6033362
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/createPropertyRule.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 { get } from 'lodash';
+import { Entity } from '@backstage/catalog-model';
+import { createCatalogPermissionRule } from './util';
+
+export const createPropertyRule = (propertyType: 'metadata' | 'spec') =>
+ createCatalogPermissionRule({
+ name: `HAS_${propertyType.toUpperCase()}`,
+ description: `Allow entities which have the specified ${propertyType} subfield.`,
+ apply: (resource: Entity, key: string, value?: string) => {
+ const foundValue = get(resource[propertyType], key);
+ if (value !== undefined) {
+ return value === foundValue;
+ }
+ return !!foundValue;
+ },
+ toQuery: (key: string, value?: string) => ({
+ key: `${propertyType}.${key}`,
+ ...(value !== undefined && { values: [value] }),
+ }),
+ });
diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts
new file mode 100644
index 0000000000..1596270907
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { hasAnnotation } from './hasAnnotation';
+
+describe('hasAnnotation permission rule', () => {
+ describe('apply', () => {
+ it('returns false when specified annotation is not present', () => {
+ expect(
+ hasAnnotation.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ annotations: {
+ 'other-annotation': 'foo',
+ },
+ },
+ },
+ 'backstage.io/test-annotation',
+ ),
+ ).toEqual(false);
+ });
+
+ it('returns false when no annotations are present', () => {
+ expect(
+ hasAnnotation.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ },
+ },
+ 'backstage.io/test-annotation',
+ ),
+ ).toEqual(false);
+ });
+
+ it('returns true when specified annotation is present', () => {
+ expect(
+ hasAnnotation.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ annotations: {
+ 'other-annotation': 'foo',
+ 'backstage.io/test-annotation': 'bar',
+ },
+ },
+ },
+ 'backstage.io/test-annotation',
+ ),
+ ).toEqual(true);
+ });
+ });
+
+ describe('toQuery', () => {
+ it('returns an appropriate catalog-backend filter', () => {
+ expect(hasAnnotation.toQuery('backstage.io/test-annotation')).toEqual({
+ key: 'metadata.annotations.backstage.io/test-annotation',
+ });
+ });
+ });
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts
new file mode 100644
index 0000000000..81ebd52789
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Entity } from '@backstage/catalog-model';
+import { createCatalogPermissionRule } from './util';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for the presence of an annotation on a given entity.
+ *
+ * @public
+ */
+export const hasAnnotation = createCatalogPermissionRule({
+ name: 'HAS_ANNOTATION',
+ description:
+ 'Allow entities which are annotated with the specified annotation',
+ apply: (resource: Entity, annotation: string) =>
+ !!resource.metadata.annotations?.hasOwnProperty(annotation),
+ toQuery: (annotation: string) => ({
+ key: `metadata.annotations.${annotation}`,
+ }),
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts
new file mode 100644
index 0000000000..a1b9cb5ad0
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.test.ts
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { hasLabel } from './hasLabel';
+
+describe('hasLabel permission rule', () => {
+ describe('apply', () => {
+ it('returns false when specified label is not present', () => {
+ expect(
+ hasLabel.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ labels: {
+ somelabel: 'foo',
+ },
+ },
+ },
+ 'backstage.io/testlabel',
+ ),
+ ).toEqual(false);
+ });
+
+ it('returns false when no annotations are present', () => {
+ expect(
+ hasLabel.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ },
+ },
+ 'backstage.io/testlabel',
+ ),
+ ).toEqual(false);
+ });
+
+ it('returns true when specified annotation is present', () => {
+ expect(
+ hasLabel.apply(
+ {
+ apiVersion: 'backstage.io/v1alpha1',
+ kind: 'Component',
+ metadata: {
+ name: 'test-component',
+ labels: {
+ somelabel: 'foo',
+ 'backstage.io/testlabel': 'bar',
+ },
+ },
+ },
+ 'backstage.io/testlabel',
+ ),
+ ).toEqual(true);
+ });
+ });
+
+ describe('toQuery', () => {
+ it('returns an appropriate catalog-backend filter', () => {
+ expect(hasLabel.toQuery('backstage.io/testlabel')).toEqual({
+ key: 'metadata.labels.backstage.io/testlabel',
+ });
+ });
+ });
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/hasLabel.ts b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts
new file mode 100644
index 0000000000..04b00d68fa
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasLabel.ts
@@ -0,0 +1,33 @@
+/*
+ * 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 { Entity } from '@backstage/catalog-model';
+import { createCatalogPermissionRule } from './util';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for entities with a specified label in its metadata.
+ * @public
+ */
+export const hasLabel = createCatalogPermissionRule({
+ name: 'HAS_LABEL',
+ description: 'Allow entities which have the specified label metadata.',
+ apply: (resource: Entity, label: string) =>
+ !!resource.metadata.labels?.hasOwnProperty(label),
+ toQuery: (label: string) => ({
+ key: `metadata.labels.${label}`,
+ }),
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/hasMetadata.ts b/plugins/catalog-backend/src/permissions/rules/hasMetadata.ts
new file mode 100644
index 0000000000..f5f25a5ecf
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasMetadata.ts
@@ -0,0 +1,28 @@
+/*
+ * 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 { createPropertyRule } from './createPropertyRule';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for entities with the specified metadata subfield. Also matches on
+ * values if value is provided.
+ *
+ * The key argument to the `apply` and `toQuery` methods can be nested, such as
+ * 'field.nestedfield'.
+ * @public
+ */
+export const hasMetadata = createPropertyRule('metadata');
diff --git a/plugins/catalog-backend/src/permissions/rules/hasSpec.ts b/plugins/catalog-backend/src/permissions/rules/hasSpec.ts
new file mode 100644
index 0000000000..891cf1d58c
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/hasSpec.ts
@@ -0,0 +1,28 @@
+/*
+ * 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 { createPropertyRule } from './createPropertyRule';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for entities with the specified spec subfield. Also matches on values
+ * if value is provided.
+ *
+ * The key argument to the `apply` and `toQuery` methods can be nested, such as
+ * 'field.nestedfield'.
+ * @public
+ */
+export const hasSpec = createPropertyRule('spec');
diff --git a/plugins/catalog-backend/src/permissions/rules/index.ts b/plugins/catalog-backend/src/permissions/rules/index.ts
new file mode 100644
index 0000000000..4eec796c74
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/index.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { hasAnnotation } from './hasAnnotation';
+import { isEntityKind } from './isEntityKind';
+import { isEntityOwner } from './isEntityOwner';
+import { hasLabel } from './hasLabel';
+import { hasMetadata } from './hasMetadata';
+import { hasSpec } from './hasSpec';
+
+/**
+ * These permission rules can be used to conditionally filter catalog entities
+ * or describe a user's access to the entities.
+ * @public
+ */
+export const permissionRules = {
+ hasAnnotation,
+ hasLabel,
+ hasMetadata,
+ hasSpec,
+ isEntityKind,
+ isEntityOwner,
+};
+
+export { createCatalogPermissionRule } from './util';
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts
new file mode 100644
index 0000000000..e11e102728
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.test.ts
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Entity } from '@backstage/catalog-model';
+import { isEntityKind } from './isEntityKind';
+
+describe('isEntityKind', () => {
+ describe('apply', () => {
+ it('returns true when entity is the correct kind', () => {
+ const component: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'some-component',
+ },
+ };
+ expect(isEntityKind.apply(component, ['b'])).toBe(true);
+ });
+
+ it('returns false when entity is not the correct kind', () => {
+ const component: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'some-component',
+ },
+ };
+ expect(isEntityKind.apply(component, ['c'])).toBe(false);
+ });
+ });
+
+ describe('toQuery', () => {
+ it('returns an appropriate catalog-backend filter', () => {
+ expect(isEntityKind.toQuery(['b'])).toEqual({
+ key: 'kind',
+ values: ['b'],
+ });
+ });
+ });
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts
new file mode 100644
index 0000000000..6356c94dc4
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Entity } from '@backstage/catalog-model';
+import { EntitiesSearchFilter } from '../../catalog/types';
+import { createCatalogPermissionRule } from './util';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for entities with a specified kind.
+ * @public
+ */
+export const isEntityKind = createCatalogPermissionRule({
+ name: 'IS_ENTITY_KIND',
+ description: 'Allow entities with the specified kind',
+ apply(resource: Entity, kinds: string[]) {
+ const resourceKind = resource.kind.toLocaleLowerCase('en-US');
+ return kinds.some(kind => kind.toLocaleLowerCase('en-US') === resourceKind);
+ },
+ toQuery(kinds: string[]): EntitiesSearchFilter {
+ return {
+ key: 'kind',
+ values: kinds.map(kind => kind.toLocaleLowerCase('en-US')),
+ };
+ },
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts
new file mode 100644
index 0000000000..282d2558ef
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.test.ts
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Entity } from '@backstage/catalog-model';
+import { isEntityOwner } from './isEntityOwner';
+
+describe('isEntityOwner', () => {
+ describe('apply', () => {
+ it('returns true when entity is owned by the given user', () => {
+ const component: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'some-component',
+ },
+ relations: [
+ {
+ type: 'ownedBy',
+ target: {
+ kind: 'user',
+ namespace: 'default',
+ name: 'spiderman',
+ },
+ },
+ ],
+ };
+ expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe(
+ true,
+ );
+ });
+
+ it('returns false when entity is not owned by the given user', () => {
+ const component: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'some-component',
+ },
+ relations: [
+ {
+ type: 'ownedBy',
+ target: {
+ kind: 'user',
+ namespace: 'default',
+ name: 'green-goblin',
+ },
+ },
+ ],
+ };
+ expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe(
+ false,
+ );
+ });
+
+ it('returns false when entity does not have an owner', () => {
+ const component: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'some-component',
+ },
+ };
+ expect(isEntityOwner.apply(component, ['user:default/spiderman'])).toBe(
+ false,
+ );
+ });
+ });
+
+ describe('toQuery', () => {
+ it('returns an appropriate catalog-backend filter', () => {
+ expect(isEntityOwner.toQuery(['user:default/spiderman'])).toEqual({
+ key: 'relations.ownedBy',
+ values: ['user:default/spiderman'],
+ });
+ });
+ });
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts
new file mode 100644
index 0000000000..3176b31b87
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/isEntityOwner.ts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ Entity,
+ RELATION_OWNED_BY,
+ stringifyEntityRef,
+} from '@backstage/catalog-model';
+import { createCatalogPermissionRule } from './util';
+
+/**
+ * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which
+ * filters for entities with a specified owner.
+ * @public
+ */
+export const isEntityOwner = createCatalogPermissionRule({
+ name: 'IS_ENTITY_OWNER',
+ description: 'Allow entities owned by the current user',
+ apply: (resource: Entity, claims: string[]) => {
+ if (!resource.relations) {
+ return false;
+ }
+
+ return resource.relations
+ .filter(relation => relation.type === RELATION_OWNED_BY)
+ .some(relation => claims.includes(stringifyEntityRef(relation.target)));
+ },
+ toQuery: (claims: string[]) => ({
+ key: 'relations.ownedBy',
+ values: claims,
+ }),
+});
diff --git a/plugins/catalog-backend/src/permissions/rules/util.ts b/plugins/catalog-backend/src/permissions/rules/util.ts
new file mode 100644
index 0000000000..7ef0ca3546
--- /dev/null
+++ b/plugins/catalog-backend/src/permissions/rules/util.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 { Entity } from '@backstage/catalog-model';
+import { makeCreatePermissionRule } from '@backstage/plugin-permission-node';
+import { EntitiesSearchFilter } from '../../catalog/types';
+
+/**
+ * Helper function for creating correctly-typed
+ * {@link @backstage/plugin-permission-node#PermissionRule}s for the
+ * catalog-backend.
+ *
+ * @public
+ */
+export const createCatalogPermissionRule = makeCreatePermissionRule<
+ Entity,
+ EntitiesSearchFilter
+>();
diff --git a/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts b/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts
new file mode 100644
index 0000000000..82bedec573
--- /dev/null
+++ b/plugins/catalog-backend/src/service/AuthorizedRefreshService.test.ts
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { NotAllowedError } from '@backstage/errors';
+import { AuthorizeResult } from '@backstage/plugin-permission-common';
+import { ServerPermissionClient } from '@backstage/plugin-permission-node';
+import { AuthorizedRefreshService } from './AuthorizedRefreshService';
+
+describe('AuthorizedRefreshService', () => {
+ const refreshService = {
+ refresh: jest.fn(),
+ };
+ const permissionApi = {
+ authorize: jest.fn(),
+ };
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('throws AuthorizationError on deny', async () => {
+ permissionApi.authorize.mockResolvedValueOnce([
+ {
+ result: AuthorizeResult.DENY,
+ },
+ ]);
+ const authorizedService = new AuthorizedRefreshService(
+ refreshService,
+ permissionApi as unknown as ServerPermissionClient,
+ );
+
+ await expect(() =>
+ authorizedService.refresh({
+ entityRef: 'some entity ref',
+ authorizationToken: 'some auth token',
+ }),
+ ).rejects.toThrowError(NotAllowedError);
+ });
+
+ it('calls refresh on allow', async () => {
+ permissionApi.authorize.mockResolvedValueOnce([
+ {
+ result: AuthorizeResult.ALLOW,
+ },
+ ]);
+ const authorizedService = new AuthorizedRefreshService(
+ refreshService,
+ permissionApi as unknown as ServerPermissionClient,
+ );
+
+ const options = {
+ entityRef: 'some entity ref',
+ authorizationToken: 'some auth token',
+ };
+ await authorizedService.refresh(options);
+
+ expect(refreshService.refresh).toHaveBeenCalledWith(options);
+ });
+});
diff --git a/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts
new file mode 100644
index 0000000000..800bdcf1b9
--- /dev/null
+++ b/plugins/catalog-backend/src/service/AuthorizedRefreshService.ts
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { NotAllowedError } from '@backstage/errors';
+import { catalogEntityRefreshPermission } from '@backstage/plugin-catalog-common';
+import {
+ AuthorizeResult,
+ PermissionAuthorizer,
+} from '@backstage/plugin-permission-common';
+import { RefreshOptions, RefreshService } from './types';
+
+export class AuthorizedRefreshService implements RefreshService {
+ constructor(
+ private readonly service: RefreshService,
+ private readonly permissionApi: PermissionAuthorizer,
+ ) {}
+
+ async refresh(options: RefreshOptions) {
+ const authorizeResponse = (
+ await this.permissionApi.authorize(
+ [
+ {
+ permission: catalogEntityRefreshPermission,
+ resourceRef: options.entityRef,
+ },
+ ],
+ { token: options.authorizationToken },
+ )
+ )[0];
+ if (authorizeResponse.result !== AuthorizeResult.ALLOW) {
+ throw new NotAllowedError();
+ }
+ await this.service.refresh(options);
+ }
+}
diff --git a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts
index 1618ef8d7b..36d4347ede 100644
--- a/plugins/catalog-backend/src/service/NextCatalogBuilder.ts
+++ b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts
@@ -17,6 +17,7 @@
import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common';
import {
DefaultNamespaceEntityPolicy,
+ Entity,
EntityPolicies,
EntityPolicy,
FieldFormatEntityPolicy,
@@ -29,7 +30,7 @@ import { ScmIntegrations } from '@backstage/integration';
import { createHash } from 'crypto';
import { Router } from 'express';
import lodash from 'lodash';
-import { EntitiesCatalog } from '../catalog';
+import { EntitiesCatalog, EntitiesSearchFilter } from '../catalog';
import {
DatabaseLocationsCatalog,
LocationsCatalog,
@@ -77,17 +78,22 @@ import {
} from '../processing/refresh';
import { createNextRouter } from './NextRouter';
import { DefaultRefreshService } from './DefaultRefreshService';
+import { AuthorizedRefreshService } from './AuthorizedRefreshService';
import { DefaultCatalogRulesEnforcer } from '../ingestion/CatalogRules';
import { Config } from '@backstage/config';
import { Logger } from 'winston';
import { LocationService } from './types';
import { connectEntityProviders } from '../processing/connectEntityProviders';
+import { permissionRules as catalogPermissionRules } from '../permissions/rules';
+import { PermissionAuthorizer } from '@backstage/plugin-permission-common';
+import { PermissionRule } from '@backstage/plugin-permission-node';
export type CatalogEnvironment = {
logger: Logger;
database: PluginDatabaseManager;
config: Config;
reader: UrlReader;
+ permissions: PermissionAuthorizer;
};
/**
@@ -125,6 +131,11 @@ export class NextCatalogBuilder {
maxSeconds: 150,
});
private locationAnalyzer: LocationAnalyzer | undefined = undefined;
+ private permissionRules: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ unknown[]
+ >[];
constructor(env: CatalogEnvironment) {
this.env = env;
@@ -136,6 +147,7 @@ export class NextCatalogBuilder {
this.processors = [];
this.processorsReplace = false;
this.parser = undefined;
+ this.permissionRules = Object.values(catalogPermissionRules);
}
/**
@@ -317,6 +329,23 @@ export class NextCatalogBuilder {
return this;
}
+ /**
+ * Adds additional permission rules. Permission rules are used to evaluate
+ * catalog resources against queries. See
+ * {@link @backstage/plugin-permission-node#PermissionRule}.
+ *
+ * @param permissionRules - Additional permission rules
+ */
+ addPermissionRules(
+ ...permissionRules: PermissionRule<
+ Entity,
+ EntitiesSearchFilter,
+ unknown[]
+ >[]
+ ) {
+ this.permissionRules.push(...permissionRules);
+ }
+
/**
* Wires up and returns all of the component parts of the catalog
*/
@@ -329,7 +358,7 @@ export class NextCatalogBuilder {
locationService: LocationService;
router: Router;
}> {
- const { config, database, logger } = this.env;
+ const { config, database, logger, permissions } = this.env;
const policy = this.buildEntityPolicy();
const processors = this.buildProcessors();
@@ -383,9 +412,10 @@ export class NextCatalogBuilder {
locationStore,
orchestrator,
);
- const refreshService = new DefaultRefreshService({
- database: processingDatabase,
- });
+ const refreshService = new AuthorizedRefreshService(
+ new DefaultRefreshService({ database: processingDatabase }),
+ permissions,
+ );
const router = await createNextRouter({
entitiesCatalog,
locationAnalyzer,
@@ -393,6 +423,7 @@ export class NextCatalogBuilder {
refreshService,
logger,
config,
+ permissionRules: this.permissionRules,
});
await connectEntityProviders(processingDatabase, entityProviders);
diff --git a/plugins/catalog-backend/src/service/NextRouter.test.ts b/plugins/catalog-backend/src/service/NextRouter.test.ts
index 6bc4481425..e835c4620a 100644
--- a/plugins/catalog-backend/src/service/NextRouter.test.ts
+++ b/plugins/catalog-backend/src/service/NextRouter.test.ts
@@ -24,6 +24,7 @@ import { EntitiesCatalog } from '../catalog';
import { LocationService, RefreshService } from './types';
import { basicEntityFilter } from './request';
import { createNextRouter } from './NextRouter';
+import { AuthorizeResult } from '@backstage/plugin-permission-common';
describe('createNextRouter readonly disabled', () => {
let entitiesCatalog: jest.Mocked;
@@ -51,6 +52,7 @@ describe('createNextRouter readonly disabled', () => {
logger: getVoidLogger(),
refreshService,
config: new ConfigReader(undefined),
+ permissionRules: [],
});
app = express().use(router);
});
@@ -64,10 +66,12 @@ describe('createNextRouter readonly disabled', () => {
const response = await request(app)
.post('/refresh')
.set('Content-Type', 'application/json')
+ .set('authorization', 'Bearer someauthtoken')
.send({ entityRef: 'Component/default:foo' });
expect(response.status).toBe(200);
expect(refreshService.refresh).toHaveBeenCalledWith({
entityRef: 'Component/default:foo',
+ authorizationToken: 'someauthtoken',
});
});
});
@@ -336,6 +340,7 @@ describe('createNextRouter readonly enabled', () => {
readonly: true,
},
}),
+ permissionRules: [],
});
app = express().use(router);
});
@@ -429,3 +434,72 @@ describe('createNextRouter readonly enabled', () => {
});
});
});
+
+describe('NextRouter permissioning', () => {
+ let entitiesCatalog: jest.Mocked;
+ let locationService: jest.Mocked;
+ let app: express.Express;
+ let refreshService: RefreshService;
+
+ const fakeRule = {
+ name: 'FAKE_RULE',
+ description: 'fake rule',
+ apply: () => true,
+ toQuery: () => ({ key: '', values: [] }),
+ };
+
+ beforeAll(async () => {
+ entitiesCatalog = {
+ entities: jest.fn(),
+ removeEntityByUid: jest.fn(),
+ batchAddOrUpdateEntities: jest.fn(),
+ entityAncestry: jest.fn(),
+ };
+ locationService = {
+ getLocation: jest.fn(),
+ createLocation: jest.fn(),
+ listLocations: jest.fn(),
+ deleteLocation: jest.fn(),
+ };
+ refreshService = { refresh: jest.fn() };
+ const router = await createNextRouter({
+ entitiesCatalog,
+ locationService,
+ logger: getVoidLogger(),
+ refreshService,
+ config: new ConfigReader(undefined),
+ permissionRules: [fakeRule],
+ });
+ app = express().use(router);
+ });
+
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ it('accepts and evaluates conditions at the apply-conditions endpoint', async () => {
+ const spideySense: Entity = {
+ apiVersion: 'a',
+ kind: 'b',
+ metadata: {
+ name: 'spidey-sense',
+ },
+ };
+ entitiesCatalog.entities.mockResolvedValueOnce({
+ entities: [spideySense],
+ pageInfo: { hasNextPage: false },
+ });
+
+ const requestBody = {
+ resourceType: 'catalog-entity',
+ resourceRef: 'component:default/spidey-sense',
+ conditions: { rule: 'FAKE_RULE', params: ['user:default/spiderman'] },
+ };
+ const response = await request(app)
+ .post('/.well-known/backstage/permissions/apply-conditions')
+ .send(requestBody);
+
+ expect(response.status).toBe(200);
+ expect(response.body).toEqual({ result: AuthorizeResult.ALLOW });
+ });
+});
diff --git a/plugins/catalog-backend/src/service/NextRouter.ts b/plugins/catalog-backend/src/service/NextRouter.ts
index 6352f96c59..5338f58f91 100644
--- a/plugins/catalog-backend/src/service/NextRouter.ts
+++ b/plugins/catalog-backend/src/service/NextRouter.ts
@@ -17,16 +17,23 @@
import { errorHandler } from '@backstage/backend-common';
import {
analyzeLocationSchema,
+ Entity,
locationSpecSchema,
+ parseEntityRef,
stringifyEntityRef,
} from '@backstage/catalog-model';
import { Config } from '@backstage/config';
import { NotFoundError } from '@backstage/errors';
+import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common';
+import {
+ createPermissionIntegrationRouter,
+ PermissionRule,
+} from '@backstage/plugin-permission-node';
import express from 'express';
import Router from 'express-promise-router';
import { Logger } from 'winston';
import yn from 'yn';
-import { EntitiesCatalog } from '../catalog';
+import { EntitiesCatalog, EntitiesSearchFilter } from '../catalog';
import { LocationAnalyzer } from '../ingestion/types';
import {
basicEntityFilter,
@@ -35,7 +42,7 @@ import {
parseEntityTransformParams,
} from '../service/request';
import { disallowReadonlyMode, validateRequestBody } from '../service/util';
-import { RefreshService, RefreshOptions, LocationService } from './types';
+import { RefreshOptions, LocationService, RefreshService } from './types';
export interface NextRouterOptions {
entitiesCatalog?: EntitiesCatalog;
@@ -44,6 +51,7 @@ export interface NextRouterOptions {
refreshService?: RefreshService;
logger: Logger;
config: Config;
+ permissionRules?: PermissionRule[];
}
export async function createNextRouter(
@@ -56,6 +64,7 @@ export async function createNextRouter(
refreshService,
config,
logger,
+ permissionRules,
} = options;
const router = Router();
@@ -70,6 +79,10 @@ export async function createNextRouter(
if (refreshService) {
router.post('/refresh', async (req, res) => {
const refreshOptions: RefreshOptions = req.body;
+ refreshOptions.authorizationToken = getBearerToken(
+ req.header('authorization'),
+ );
+
await refreshService.refresh(refreshOptions);
res.status(200).send();
});
@@ -77,6 +90,14 @@ export async function createNextRouter(
if (entitiesCatalog) {
router
+ .use(
+ createPermissionIntegrationRouter({
+ resourceType: RESOURCE_TYPE_CATALOG_ENTITY,
+ getResource: resourceRef =>
+ getEntityResource(resourceRef, entitiesCatalog),
+ rules: permissionRules ?? [],
+ }),
+ )
.get('/entities', async (req, res) => {
const { entities, pageInfo } = await entitiesCatalog.entities({
filter: parseEntityFilterParams(req.query),
@@ -182,3 +203,30 @@ export async function createNextRouter(
router.use(errorHandler());
return router;
}
+
+async function getEntityResource(
+ resourceRef: string,
+ entitiesCatalog: EntitiesCatalog,
+): Promise {
+ const parsed = parseEntityRef(resourceRef);
+
+ const { entities } = await entitiesCatalog.entities({
+ filter: basicEntityFilter({
+ kind: parsed.kind,
+ 'metadata.namespace': parsed.namespace,
+ 'metadata.name': parsed.name,
+ }),
+ });
+
+ return entities[0];
+}
+
+function getBearerToken(
+ authorizationHeader: string | undefined,
+): string | undefined {
+ if (typeof authorizationHeader !== 'string') {
+ return undefined;
+ }
+ const matches = authorizationHeader.match(/Bearer\s+(\S+)/i);
+ return matches?.[1];
+}
diff --git a/plugins/catalog-backend/src/service/standaloneServer.ts b/plugins/catalog-backend/src/service/standaloneServer.ts
index 7aae3cd47c..8824c3b0d6 100644
--- a/plugins/catalog-backend/src/service/standaloneServer.ts
+++ b/plugins/catalog-backend/src/service/standaloneServer.ts
@@ -17,6 +17,8 @@
import {
createServiceBuilder,
loadBackendConfig,
+ ServerTokenManager,
+ SingleHostDiscovery,
UrlReaders,
useHotMemoize,
} from '@backstage/backend-common';
@@ -25,6 +27,7 @@ import { Logger } from 'winston';
import { DatabaseManager } from '../legacy/database';
import { CatalogBuilder } from '../legacy/service/CatalogBuilder';
import { createRouter } from '../legacy/service';
+import { ServerPermissionClient } from '@backstage/plugin-permission-node';
export interface ServerOptions {
port: number;
@@ -42,6 +45,12 @@ export async function startStandaloneServer(
const db = useHotMemoize(module, () =>
DatabaseManager.createInMemoryDatabaseConnection(),
);
+ const discovery = SingleHostDiscovery.fromConfig(config);
+ const tokenManager = ServerTokenManager.fromConfig(config, { logger });
+ const permissions = ServerPermissionClient.fromConfig(config, {
+ discovery,
+ tokenManager,
+ });
logger.debug('Creating application...');
const builder = new CatalogBuilder({
@@ -49,6 +58,7 @@ export async function startStandaloneServer(
database: { getClient: () => db },
config,
reader,
+ permissions,
});
const { entitiesCatalog, locationsCatalog, higherOrderOperation } =
await builder.build();
diff --git a/plugins/catalog-backend/src/service/types.ts b/plugins/catalog-backend/src/service/types.ts
index 05d3d00f4d..5e2bf2a599 100644
--- a/plugins/catalog-backend/src/service/types.ts
+++ b/plugins/catalog-backend/src/service/types.ts
@@ -34,6 +34,7 @@ export interface LocationService {
export type RefreshOptions = {
/** The reference to a single entity that should be refreshed */
entityRef: string;
+ authorizationToken?: string;
};
/**
diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json
index fe52727176..b95e65034c 100644
--- a/plugins/catalog-graphql/package.json
+++ b/plugins/catalog-graphql/package.json
@@ -45,9 +45,9 @@
"devDependencies": {
"@backstage/cli": "^0.10.3",
"@backstage/test-utils": "^0.2.0",
- "@graphql-codegen/cli": "^1.21.3",
- "@graphql-codegen/typescript": "^1.17.7",
- "@graphql-codegen/typescript-resolvers": "^1.17.7",
+ "@graphql-codegen/cli": "^2.3.1",
+ "@graphql-codegen/typescript": "^2.4.2",
+ "@graphql-codegen/typescript-resolvers": "^2.4.2",
"eslint-plugin-graphql": "^4.0.0",
"msw": "^0.35.0"
},
diff --git a/plugins/home/README.md b/plugins/home/README.md
index a09c85775b..b3b492be8e 100644
--- a/plugins/home/README.md
+++ b/plugins/home/README.md
@@ -1,9 +1,5 @@
# Home
-Development is ongoing. You can follow the progress and contribute at the Backstage [Home Project Board](https://github.com/backstage/backstage/projects/7) or reach out to us in the [`#support` Discord channel](https://discord.com/channels/687207715902193673/687235481154617364).
-
-## Overview
-
The Home plugin introduces a system for composing a Home Page for Backstage in order to surface relevant info and provide convenient shortcuts for common tasks. It's designed with composability in mind with an open ecosystem that allows anyone to contribute with any component, to be included in any Home Page.
For App Integrators, the system is designed to be composable to give total freedom in designing a Home Page that suits the needs of the organization. From the perspective of a Component Developer who wishes to contribute with building blocks to be included in Home Pages, there's a convenient interface for bundling the different parts and exporting them with both error boundary and lazy loading handled under the surface.
@@ -90,6 +86,12 @@ Additionally, the App Integrator is provided an escape hatch in case the way the
## Contributing
+### Homepage Components
+
We believe that people have great ideas for what makes a useful Home Page, and we want to make it easy for every to benefit from the effort you put in to create something cool for the Home Page. Therefore, a great way of contributing is by simply creating more Home Page Components, than can then be used by everyone when composing their own Home Page. If they are tightly coupled to an existing plugin, it is recommended to allow them to live within that plugin, for convenience and to limit complex dependencies. On the other hand, if there's no clear plugin that the component is based on, it's also fine to contribute them into the [home plugin](/plugins/home/src/homePageComponents)
Additionally, the API is at a very early state, so contributing with additional use cases may expose weaknesses in the current solution that we may iterate on, to provide more flexibility and ease of use for those who wish to develop components for the Home Page.
+
+### Homepage Templates
+
+We are hoping that we together can build up a collection of Homepage templates. We therefore put together a place where we can collect all the templates for the Home Plugin in the [storybook](https://backstage.io/storybook/?path=/story/plugins-home-templates). If you would like to contribute with a template, start by taking a look at the [DefaultTemplate storybook example to create your own](/plugins/home/src/templates/DefaultTemplate.stories.tsx), and then open a PR with your suggestion.
diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md
index 99d88fa4b5..fab2b05bb6 100644
--- a/plugins/home/api-report.md
+++ b/plugins/home/api-report.md
@@ -7,6 +7,7 @@
import { BackstagePlugin } from '@backstage/core-plugin-api';
import { Extension } from '@backstage/core-plugin-api';
+import { default as React_2 } from 'react';
import { ReactNode } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
@@ -64,10 +65,9 @@ export const ComponentTabs: ({
}[];
}) => JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "ComponentRenderer" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createCardExtension" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "CardExtensionProps" needs to be exported by the entry point index.d.ts
//
-// @public (undocumented)
+// @public
export function createCardExtension({
title,
components,
@@ -76,15 +76,7 @@ export function createCardExtension({
title: string;
components: () => Promise;
name?: string;
-}): Extension<
- ({
- Renderer,
- title: overrideTitle,
- ...childProps
- }: ComponentRenderer & {
- title?: string;
- } & T) => JSX.Element
->;
+}): Extension<(props: CardExtensionProps) => JSX.Element>;
// Warning: (ae-missing-release-tag) "HeaderWorldClock" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -95,6 +87,12 @@ export const HeaderWorldClock: ({
clockConfigs: ClockConfig[];
}) => JSX.Element | null;
+// @public
+export const HomePageCompanyLogo: (props: {
+ logo?: ReactNode;
+ className?: string | undefined;
+}) => JSX.Element;
+
// Warning: (ae-missing-release-tag) "HomepageCompositionRoot" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -103,18 +101,26 @@ export const HomepageCompositionRoot: (props: {
children?: ReactNode;
}) => JSX.Element;
+// Warning: (ae-forgotten-export) The symbol "ComponentRenderer" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "HomePageRandomJoke" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
-export const HomePageRandomJoke: ({
- Renderer,
- title: overrideTitle,
- ...childProps
-}: ComponentRenderer & {
- title?: string | undefined;
-} & {
- defaultCategory?: 'any' | 'programming' | undefined;
-}) => JSX.Element;
+export const HomePageRandomJoke: (
+ props: ComponentRenderer & {
+ title?: string | undefined;
+ } & {
+ defaultCategory?: 'any' | 'programming' | undefined;
+ },
+) => JSX.Element;
+
+// Warning: (ae-forgotten-export) The symbol "ToolkitContentProps" needs to be exported by the entry point index.d.ts
+//
+// @public
+export const HomePageToolkit: (
+ props: ComponentRenderer & {
+ title?: string | undefined;
+ } & ToolkitContentProps,
+) => JSX.Element;
// Warning: (ae-missing-release-tag) "homePlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -146,5 +152,5 @@ export const WelcomeTitle: () => JSX.Element;
// Warnings were encountered during analysis:
//
-// src/extensions.d.ts:16:5 - (ae-forgotten-export) The symbol "ComponentParts" needs to be exported by the entry point index.d.ts
+// src/extensions.d.ts:24:5 - (ae-forgotten-export) The symbol "ComponentParts" needs to be exported by the entry point index.d.ts
```
diff --git a/plugins/home/package.json b/plugins/home/package.json
index 8b2f829efa..298b1860e9 100644
--- a/plugins/home/package.json
+++ b/plugins/home/package.json
@@ -24,6 +24,7 @@
"@backstage/core-components": "^0.8.3",
"@backstage/core-plugin-api": "^0.4.1",
"@backstage/theme": "^0.2.14",
+ "@backstage/plugin-search": "^0.5.1",
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
diff --git a/plugins/home/src/extensions.tsx b/plugins/home/src/extensions.tsx
index 82394cf1ea..4a234f9813 100644
--- a/plugins/home/src/extensions.tsx
+++ b/plugins/home/src/extensions.tsx
@@ -26,7 +26,7 @@ export type ComponentRenderer = {
};
type ComponentParts = {
- Content: () => JSX.Element;
+ Content: (props?: any) => JSX.Element;
Actions?: () => JSX.Element;
Settings?: () => JSX.Element;
ContextProvider?: (props: any) => JSX.Element;
@@ -34,6 +34,13 @@ type ComponentParts = {
type RendererProps = { title: string } & ComponentParts;
+type CardExtensionProps = ComponentRenderer & { title?: string } & T;
+
+/**
+ * An extension creator to create card based components for the homepage
+ *
+ * @public
+ */
export function createCardExtension({
title,
components,
@@ -48,11 +55,8 @@ export function createCardExtension({
component: {
lazy: () =>
components().then(({ Content, Actions, Settings, ContextProvider }) => {
- const CardExtension = ({
- Renderer,
- title: overrideTitle,
- ...childProps
- }: ComponentRenderer & { title?: string } & T) => {
+ const CardExtension = (props: CardExtensionProps) => {
+ const { Renderer, title: overrideTitle, ...childProps } = props;
const app = useApp();
const { Progress } = app.getComponents();
const [settingsOpen, setSettingsOpen] = React.useState(false);
@@ -103,7 +107,7 @@ export function createCardExtension({
)}
-
+
);
diff --git a/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.stories.tsx b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.stories.tsx
new file mode 100644
index 0000000000..ab71eea54e
--- /dev/null
+++ b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.stories.tsx
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { TemplateBackstageLogo } from '../../templates';
+import { HomePageCompanyLogo } from '../../plugin';
+import { rootRouteRef } from '../../routes';
+import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { configApiRef } from '@backstage/core-plugin-api';
+import { ConfigReader } from '@backstage/core-app-api';
+import { Grid, makeStyles } from '@material-ui/core';
+import React, { ComponentType } from 'react';
+
+export default {
+ title: 'Plugins/Home/Components/CompanyLogo',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(
+
+
+ ,
+ {
+ mountedRoutes: { '/hello-company-logo': rootRouteRef },
+ },
+ ),
+ ],
+};
+
+const useLogoStyles = makeStyles(theme => ({
+ container: {
+ margin: theme.spacing(5, 0),
+ },
+ svg: {
+ width: 'auto',
+ height: 100,
+ },
+ path: {
+ fill: '#7df3e1',
+ },
+}));
+
+export const Default = () => {
+ const { container } = useLogoStyles();
+
+ return (
+
+
+
+ );
+};
+
+export const CustomLogo = () => {
+ const { container, svg, path } = useLogoStyles();
+
+ return (
+
+ }
+ />
+
+ );
+};
diff --git a/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.test.tsx b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.test.tsx
new file mode 100644
index 0000000000..3cd08bc70b
--- /dev/null
+++ b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.test.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { CompanyLogo } from './CompanyLogo';
+import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { configApiRef } from '@backstage/core-plugin-api';
+import { ConfigReader } from '@backstage/core-app-api';
+import { Typography } from '@material-ui/core';
+import React from 'react';
+
+describe('', () => {
+ it('should have a fall back if logo is not provided', async () => {
+ const { getByRole } = await renderInTestApp(
+
+
+ ,
+ );
+
+ expect(getByRole('heading', { name: 'My App' })).toBeInTheDocument();
+ });
+
+ it('should show provided company logo', async () => {
+ const { getByRole } = await renderInTestApp(
+ Backstage} />,
+ );
+
+ expect(getByRole('heading', { name: 'Backstage' })).toBeInTheDocument();
+ });
+});
diff --git a/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.tsx b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.tsx
new file mode 100644
index 0000000000..998c2d46b1
--- /dev/null
+++ b/plugins/home/src/homePageComponents/CompanyLogo/CompanyLogo.tsx
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { Typography } from '@material-ui/core';
+import { configApiRef, useApi } from '@backstage/core-plugin-api';
+import React from 'react';
+
+type CompanyLogoProps = {
+ logo?: React.ReactNode;
+ className?: string;
+};
+
+/**
+ * A component to display a company logo for the user.
+ *
+ * @public
+ */
+export const CompanyLogo = (props: CompanyLogoProps) => {
+ const { logo, className } = props;
+ const configApi = useApi(configApiRef);
+
+ return (
+
+ );
+};
diff --git a/plugins/home/src/homePageComponents/CompanyLogo/index.ts b/plugins/home/src/homePageComponents/CompanyLogo/index.ts
new file mode 100644
index 0000000000..50a8869720
--- /dev/null
+++ b/plugins/home/src/homePageComponents/CompanyLogo/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+export { CompanyLogo } from './CompanyLogo';
diff --git a/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx b/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx
new file mode 100644
index 0000000000..7fbaff08f9
--- /dev/null
+++ b/plugins/home/src/homePageComponents/Toolkit/Content.test.tsx
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { renderInTestApp } from '@backstage/test-utils';
+import React from 'react';
+import { Content } from './Content';
+
+describe('', () => {
+ test('should render list of tools', async () => {
+ const { getByText } = await renderInTestApp(
+ icon },
+ { label: 'tool 2', url: '/url-2', icon:
icon 2
},
+ ]}
+ />,
+ );
+
+ expect(getByText('tool')).toBeInTheDocument();
+ expect(getByText('tool 2')).toBeInTheDocument();
+ expect(getByText('tool').closest('a')).toHaveAttribute('href', '/url');
+ expect(getByText('tool 2').closest('a')).toHaveAttribute('href', '/url-2');
+ });
+});
diff --git a/plugins/home/src/homePageComponents/Toolkit/Content.tsx b/plugins/home/src/homePageComponents/Toolkit/Content.tsx
new file mode 100644
index 0000000000..4ee1884bd0
--- /dev/null
+++ b/plugins/home/src/homePageComponents/Toolkit/Content.tsx
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Link } from '@backstage/core-components';
+import {
+ makeStyles,
+ List,
+ ListItemIcon,
+ ListItemText,
+} from '@material-ui/core';
+import React from 'react';
+
+const useStyles = makeStyles(theme => ({
+ toolkit: {
+ display: 'flex',
+ flexWrap: 'wrap',
+ textAlign: 'center',
+ },
+ tool: {
+ margin: theme.spacing(0.5, 1),
+ },
+ label: {
+ marginTop: theme.spacing(1),
+ fontSize: '0.9em',
+ lineHeight: '1.25',
+ color: theme.palette.text.secondary,
+ },
+ icon: {
+ width: '64px',
+ height: '64px',
+ borderRadius: '50px',
+ justifyContent: 'center',
+ alignItems: 'center',
+ boxShadow: theme.shadows[1],
+ backgroundColor: theme.palette.background.default,
+ },
+}));
+
+type Tool = {
+ label: string;
+ url: string;
+ icon: React.ReactNode;
+};
+
+/**
+ * Props for Toolkit content component {@link Content}.
+ *
+ * @public
+ */
+export type ToolkitContentProps = {
+ tools: Tool[];
+};
+
+/**
+ * A component to display a list of tools for the user.
+ *
+ * @public
+ */
+export const Content = (props: ToolkitContentProps) => {
+ const classes = useStyles();
+
+ return (
+
+ {props.tools.map((tool: Tool) => (
+
+ {tool.icon}
+
+
+ ))}
+
+ );
+};
diff --git a/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx b/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx
new file mode 100644
index 0000000000..0a8e6fffbe
--- /dev/null
+++ b/plugins/home/src/homePageComponents/Toolkit/Toolkit.stories.tsx
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { TemplateBackstageLogoIcon } from '../../templates';
+import { HomePageToolkit } from '../../plugin';
+import { wrapInTestApp } from '@backstage/test-utils';
+import { Grid } from '@material-ui/core';
+import React, { ComponentType } from 'react';
+
+export default {
+ title: 'Plugins/Home/Components/Toolkit',
+ decorators: [(Story: ComponentType<{}>) => wrapInTestApp()],
+};
+
+export const Default = () => {
+ return (
+
+ ,
+ })}
+ />
+
+ );
+};
diff --git a/plugins/home/src/homePageComponents/Toolkit/index.ts b/plugins/home/src/homePageComponents/Toolkit/index.ts
new file mode 100644
index 0000000000..98e0869825
--- /dev/null
+++ b/plugins/home/src/homePageComponents/Toolkit/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { Content } from './Content';
+export type { ToolkitContentProps } from './Content';
diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts
new file mode 100644
index 0000000000..4d2802fb98
--- /dev/null
+++ b/plugins/home/src/homePageComponents/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export * from './CompanyLogo';
+export * from './Toolkit';
diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts
index a8b8e7ab14..dcd61f1fa3 100644
--- a/plugins/home/src/index.ts
+++ b/plugins/home/src/index.ts
@@ -24,6 +24,8 @@ export {
homePlugin,
HomepageCompositionRoot,
HomePageRandomJoke,
+ HomePageToolkit,
+ HomePageCompanyLogo,
ComponentAccordion,
ComponentTabs,
ComponentTab,
diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts
index b4b9f9b6ee..135ac97af0 100644
--- a/plugins/home/src/plugin.ts
+++ b/plugins/home/src/plugin.ts
@@ -19,6 +19,7 @@ import {
createRoutableExtension,
} from '@backstage/core-plugin-api';
import { createCardExtension } from './extensions';
+import { ToolkitContentProps } from './homePageComponents';
import { rootRouteRef } from './routes';
@@ -79,6 +80,21 @@ export const WelcomeTitle = homePlugin.provide(
}),
);
+/**
+ * A component to display a company logo for the user.
+ *
+ * @public
+ */
+export const HomePageCompanyLogo = homePlugin.provide(
+ createComponentExtension({
+ name: 'CompanyLogo',
+ component: {
+ lazy: () =>
+ import('./homePageComponents/CompanyLogo').then(m => m.CompanyLogo),
+ },
+ }),
+);
+
export const HomePageRandomJoke = homePlugin.provide(
createCardExtension<{ defaultCategory?: 'any' | 'programming' }>({
name: 'HomePageRandomJoke',
@@ -86,3 +102,16 @@ export const HomePageRandomJoke = homePlugin.provide(
components: () => import('./homePageComponents/RandomJoke'),
}),
);
+
+/**
+ * A component to display a list of tools for the user.
+ *
+ * @public
+ */
+export const HomePageToolkit = homePlugin.provide(
+ createCardExtension({
+ name: 'HomePageToolkit',
+ title: 'Toolkit',
+ components: () => import('./homePageComponents/Toolkit'),
+ }),
+);
diff --git a/plugins/home/src/templates/DefaultTemplate.stories.tsx b/plugins/home/src/templates/DefaultTemplate.stories.tsx
new file mode 100644
index 0000000000..18518e47a9
--- /dev/null
+++ b/plugins/home/src/templates/DefaultTemplate.stories.tsx
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {TemplateBackstageLogo} from './TemplateBackstageLogo';
+import {TemplateBackstageLogoIcon} from './TemplateBackstageLogoIcon';
+import { HomePageToolkit, HomePageCompanyLogo } from '../plugin';
+import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { Content, Page, InfoCard } from '@backstage/core-components';
+import {
+ HomePageSearchBar,
+ SearchContextProvider,
+ searchApiRef,
+ searchPlugin
+} from '@backstage/plugin-search';
+import { Grid, makeStyles } from '@material-ui/core';
+import React, { ComponentType} from 'react';
+
+
+export default {
+ title: 'Plugins/Home/Templates',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(
+ <>
+ Promise.resolve({results: []})}]]}>
+
+
+ >,
+ {
+ mountedRoutes: {'/hello-company': searchPlugin.routes.root }
+ }
+ ),
+ ],
+};
+
+const useStyles = makeStyles(theme => ({
+ search: {
+ backgroundColor: theme.palette.background.paper,
+ boxShadow: theme.shadows[1],
+ maxWidth: '60vw',
+ display: 'flex',
+ justifyContent: 'space-between',
+ padding: '8px 0',
+ borderColor: 'transparent',
+ borderRadius: '50px',
+ margin: 'auto',
+ },
+}));
+
+const useLogoStyles = makeStyles(theme => ({
+ container: {
+ margin: theme.spacing(5, 0),
+ },
+ svg: {
+ width: 'auto',
+ height: 100,
+ },
+ path: {
+ fill: '#7df3e1',
+ },
+}));
+
+export const DefaultTemplate = () => {
+ const { search } = useStyles();
+ const { svg, path, container } = useLogoStyles();
+
+ return (
+
+
+
+
+ }
+ />
+
+
+
+
+
+
+ {/* placeholder for content */}
+
+
+
+
+ ,
+ })}
+ />
+
+
+
+ {/* placeholder for content */}
+
+
+
+
+
+ {/* placeholder for content */}
+
+
+
+
+
+
+
+
+ );
+};
+
diff --git a/plugins/home/src/templates/TemplateBackstageLogo.tsx b/plugins/home/src/templates/TemplateBackstageLogo.tsx
new file mode 100644
index 0000000000..c5bca1f773
--- /dev/null
+++ b/plugins/home/src/templates/TemplateBackstageLogo.tsx
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+
+type Classes = {
+ svg: string;
+ path: string;
+}
+
+export const TemplateBackstageLogo = ({ classes }: { classes: Classes }) => {
+ return (
+
+ );
+};
diff --git a/plugins/home/src/templates/TemplateBackstageLogoIcon.tsx b/plugins/home/src/templates/TemplateBackstageLogoIcon.tsx
new file mode 100644
index 0000000000..2116b48784
--- /dev/null
+++ b/plugins/home/src/templates/TemplateBackstageLogoIcon.tsx
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import { makeStyles } from '@material-ui/core';
+
+const useStyles = makeStyles({
+ svg: {
+ width: 'auto',
+ height: 28,
+ },
+ path: {
+ fill: '#7df3e1',
+ },
+});
+
+export const TemplateBackstageLogoIcon = () => {
+ const classes = useStyles();
+
+ return (
+
+ );
+};
+
diff --git a/plugins/home/src/templates/index.ts b/plugins/home/src/templates/index.ts
new file mode 100644
index 0000000000..bfebe73cd8
--- /dev/null
+++ b/plugins/home/src/templates/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { TemplateBackstageLogoIcon } from './TemplateBackstageLogoIcon';
+export { TemplateBackstageLogo } from './TemplateBackstageLogo'
diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts
index 9060ce9239..7806160e58 100644
--- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts
+++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts
@@ -34,7 +34,9 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
},
};
- let credentialsResponse: any = new AWS.Credentials(credentials);
+ let mockedCredentials: any = undefined;
+
+ AWS.config.credentials = new AWS.Credentials(credentials);
AWSMock.setSDKInstance(AWS);
@@ -53,19 +55,25 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
const authTranslator = new AwsIamKubernetesAuthTranslator();
- jest
- .spyOn(authTranslator, 'awsGetCredentials')
- .mockImplementation(async () => credentialsResponse);
+ if (mockedCredentials) {
+ jest
+ .spyOn(authTranslator, 'awsGetCredentials')
+ .mockImplementation(async () => mockedCredentials);
+ }
- return authTranslator.decorateClusterDetailsWithAuth({
+ const response = authTranslator.decorateClusterDetailsWithAuth({
assumeRole: role,
name: 'test-cluster',
url: '',
authProvider: 'aws',
});
+
+ mockedCredentials = undefined;
+
+ return response;
});
- it('returns a signed url for aws credentials', async () => {
+ it('returns a signed url for AWS credentials', async () => {
// These credentials are not real.
// Pulled from example in docs: https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html
AWS.config.credentials = new AWS.Credentials(
@@ -87,7 +95,7 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
role = 'SomeRole';
describe('When the role is valid', () => {
- it('returns a signed url for aws credentials', async () => {
+ it('returns a signed url for AWS credentials', async () => {
const subject = await get('subject');
expect(subject.serviceAccountToken).toBeDefined();
});
@@ -101,16 +109,20 @@ describe('AwsIamKubernetesAuthTranslator tests', () => {
});
});
- describe('When no creds are returned from AWS', () => {
- it('throws unable to get aws credentials', async () => {
- credentialsResponse = new Error();
+ describe('When no AWS creds are available', () => {
+ it('throws unable to get AWS credentials', async () => {
+ mockedCredentials = new Error();
await expect(get('subject')).rejects.toThrow('No AWS credentials found.');
});
});
- describe('When invalid creds are returned from AWS', () => {
- it('throws credentials are invalid to get aws credentials', async () => {
- credentialsResponse = new AWS.Credentials(credentialsResponse);
+ describe('When invalid AWS creds are available', () => {
+ it('throws credentials are invalid to get AWS credentials', async () => {
+ const undefinedSecret: any = undefined;
+ AWS.config.credentials = new AWS.Credentials(
+ 'AKIAIOSFODNN7EXAMPLE',
+ undefinedSecret,
+ );
await expect(get('subject')).rejects.toThrow(
'Invalid AWS credentials found.',
);
diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts
index 916067ebc5..4af39d4f26 100644
--- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts
+++ b/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts
@@ -41,9 +41,7 @@ export class AwsIamKubernetesAuthTranslator
implements KubernetesAuthTranslator
{
validCredentials(creds: SigningCreds): boolean {
- return (creds?.accessKeyId &&
- creds?.secretAccessKey &&
- creds?.sessionToken) as unknown as boolean;
+ return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;
}
awsGetCredentials = async (): Promise => {
diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md
index 25a8be06c8..e743f18311 100644
--- a/plugins/permission-node/api-report.md
+++ b/plugins/permission-node/api-report.md
@@ -95,6 +95,22 @@ export const createPermissionIntegrationRouter: (options: {
getResource: (resourceRef: string) => Promise;
}) => Router;
+// @public
+export const createPermissionRule: <
+ TResource,
+ TQuery,
+ TParams extends unknown[],
+>(
+ rule: PermissionRule,
+) => PermissionRule;
+
+// @public
+export const makeCreatePermissionRule: () => <
+ TParams extends unknown[],
+>(
+ rule: PermissionRule,
+) => PermissionRule;
+
// @public
export interface PermissionPolicy {
// (undocumented)
diff --git a/plugins/permission-node/src/integration/createPermissionRule.ts b/plugins/permission-node/src/integration/createPermissionRule.ts
new file mode 100644
index 0000000000..f3a0519a70
--- /dev/null
+++ b/plugins/permission-node/src/integration/createPermissionRule.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { PermissionRule } from '../types';
+
+/**
+ * Helper function to ensure that {@link PermissionRule} definitions are typed correctly.
+ *
+ * @public
+ */
+export const createPermissionRule = <
+ TResource,
+ TQuery,
+ TParams extends unknown[],
+>(
+ rule: PermissionRule,
+) => rule;
+
+/**
+ * Helper for making plugin-specific createPermissionRule functions, that have
+ * the TResource and TQuery type parameters populated but infer the params from
+ * the supplied rule. This helps ensure that rules created for this plugin use
+ * consistent types for the resource and query.
+ *
+ * @public
+ */
+export const makeCreatePermissionRule =
+ () =>
+ (
+ rule: PermissionRule,
+ ) =>
+ createPermissionRule(rule);
diff --git a/plugins/permission-node/src/integration/index.ts b/plugins/permission-node/src/integration/index.ts
index f070d57c8f..978342e4ed 100644
--- a/plugins/permission-node/src/integration/index.ts
+++ b/plugins/permission-node/src/integration/index.ts
@@ -18,3 +18,4 @@ export * from './createConditionFactory';
export * from './createConditionExports';
export * from './createConditionTransformer';
export * from './createPermissionIntegrationRouter';
+export * from './createPermissionRule';
diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts
index e1f8823487..d257bced38 100644
--- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts
@@ -117,7 +117,7 @@ describe('catalog:register', () => {
);
});
- it('should register location in catalog and return the entity and not the generated location', async () => {
+ it('should return entityRef with the Component entity and not the generated location', async () => {
addLocation
.mockResolvedValueOnce({
entities: [],
@@ -131,6 +131,13 @@ describe('catalog:register', () => {
},
kind: 'Location',
} as Entity,
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'test',
+ },
+ kind: 'Api',
+ } as Entity,
{
metadata: {
namespace: 'default',
@@ -138,6 +145,13 @@ describe('catalog:register', () => {
},
kind: 'Component',
} as Entity,
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'test',
+ },
+ kind: 'Template',
+ } as Entity,
],
});
await action.handler({
@@ -146,32 +160,103 @@ describe('catalog:register', () => {
catalogInfoUrl: 'http://foo/var',
},
});
-
- expect(addLocation).toHaveBeenNthCalledWith(
- 1,
- {
- type: 'url',
- target: 'http://foo/var',
- },
- {},
- );
- expect(addLocation).toHaveBeenNthCalledWith(
- 2,
- {
- dryRun: true,
- type: 'url',
- target: 'http://foo/var',
- },
- {},
- );
-
expect(mockContext.output).toBeCalledWith(
'entityRef',
'component:default/test',
);
+ });
+
+ it('should return entityRef with the next non-generated entity if no Component kind can be found', async () => {
+ addLocation
+ .mockResolvedValueOnce({
+ entities: [],
+ })
+ .mockResolvedValueOnce({
+ entities: [
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'generated-1238',
+ },
+ kind: 'Location',
+ } as Entity,
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'test',
+ },
+ kind: 'Api', // should return this one
+ } as Entity,
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'test',
+ },
+ kind: 'Template',
+ } as Entity,
+ ],
+ });
+ await action.handler({
+ ...mockContext,
+ input: {
+ catalogInfoUrl: 'http://foo/var',
+ },
+ });
+ expect(mockContext.output).toBeCalledWith('entityRef', 'api:default/test');
+ });
+
+ it('should return entityRef with the first entity if no non-generated entities can be found', async () => {
+ addLocation
+ .mockResolvedValueOnce({
+ entities: [],
+ })
+ .mockResolvedValueOnce({
+ entities: [
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'generated-1238',
+ },
+ kind: 'Location',
+ } as Entity,
+ {
+ metadata: {
+ namespace: 'default',
+ name: 'generated-1238',
+ },
+ kind: 'Template',
+ } as Entity,
+ ],
+ });
+ await action.handler({
+ ...mockContext,
+ input: {
+ catalogInfoUrl: 'http://foo/var',
+ },
+ });
expect(mockContext.output).toBeCalledWith(
- 'catalogInfoUrl',
- 'http://foo/var',
+ 'entityRef',
+ 'location:default/generated-1238',
+ );
+ });
+
+ it('should not return entityRef if there are no entites', async () => {
+ addLocation
+ .mockResolvedValueOnce({
+ entities: [],
+ })
+ .mockResolvedValueOnce({
+ entities: [],
+ });
+ await action.handler({
+ ...mockContext,
+ input: {
+ catalogInfoUrl: 'http://foo/var',
+ },
+ });
+ expect(mockContext.output).not.toBeCalledWith(
+ 'entityRef',
+ expect.any(String),
);
});
diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts
index 0c08131925..249939b0e6 100644
--- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts
+++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts
@@ -125,9 +125,22 @@ export function createCatalogRegisterAction(options: {
if (result.entities.length > 0) {
const { entities } = result;
- const entity =
- entities.find(e => !e.metadata.name.startsWith('generated-')) ??
- entities[0];
+ let entity: any;
+ // prioritise 'Component' type as it is the most central kind of entity
+ entity = entities.find(
+ (e: any) =>
+ !e.metadata.name.startsWith('generated-') &&
+ e.kind === 'Component',
+ );
+ if (!entity) {
+ entity = entities.find(
+ (e: any) => !e.metadata.name.startsWith('generated-'),
+ );
+ }
+ if (!entity) {
+ entity = entities[0];
+ }
+
ctx.output('entityRef', stringifyEntityRef(entity));
}
} catch (e) {
diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx
new file mode 100644
index 0000000000..48f0cbaa1e
--- /dev/null
+++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.stories.tsx
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { rootRouteRef, HomePageSearchBar } from '../../plugin';
+import { searchApiRef } from '../../apis';
+import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { Grid, makeStyles } from '@material-ui/core';
+import React, { ComponentType } from 'react';
+
+export default {
+ title: 'Plugins/Home/Components/SearchBar',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(
+ <>
+ Promise.resolve({ results: [] }) }],
+ ]}
+ >
+
+
+ >,
+ {
+ mountedRoutes: { '/hello-search': rootRouteRef },
+ },
+ ),
+ ],
+};
+
+const useStyles = makeStyles(theme => ({
+ search: {
+ backgroundColor: theme.palette.background.paper,
+ boxShadow: theme.shadows[1],
+ maxWidth: '60vw',
+ display: 'flex',
+ justifyContent: 'space-between',
+ padding: '8px 0',
+ borderColor: 'transparent',
+ borderRadius: '50px',
+ margin: 'auto',
+ },
+}));
+
+export const Default = () => {
+ const { search } = useStyles();
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/plugins/search/src/components/SearchModal/SearchModal.tsx b/plugins/search/src/components/SearchModal/SearchModal.tsx
index 8b4da51592..c7ca33005d 100644
--- a/plugins/search/src/components/SearchModal/SearchModal.tsx
+++ b/plugins/search/src/components/SearchModal/SearchModal.tsx
@@ -25,7 +25,7 @@ import {
List,
Paper,
} from '@material-ui/core';
-import { Launch } from '@material-ui/icons/';
+import LaunchIcon from '@material-ui/icons/Launch';
import { makeStyles } from '@material-ui/core/styles';
import { SearchBar } from '../SearchBar';
import { DefaultResultListItem } from '../DefaultResultListItem';
@@ -96,7 +96,7 @@ export const Modal = ({ open = true, toggleModal }: SearchModalProps) => {
View Full Results
-
+
diff --git a/plugins/tech-insights/src/components/BooleanCheck/BooleanCheck.tsx b/plugins/tech-insights/src/components/BooleanCheck/BooleanCheck.tsx
index e38e0aa7b3..a37a5ee0b4 100644
--- a/plugins/tech-insights/src/components/BooleanCheck/BooleanCheck.tsx
+++ b/plugins/tech-insights/src/components/BooleanCheck/BooleanCheck.tsx
@@ -41,7 +41,7 @@ export const BooleanCheck = ({ checkResult }: Prop) => {
return (
{checkResult.map((check, index) => (
-
+ {
const [sidebars, setSidebars] = useState();
const [dom, setDom] = useState(null);
+ // sidebar pinned status to be used in computing CSS style injections
+ const { isPinned } = useContext(SidebarPinStateContext);
+
const updateSidebarPosition = useCallback(() => {
if (!dom || !sidebars) return;
// set sidebar height so they don't initially render in wrong position
@@ -252,7 +256,9 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => {
transition: none !important
}
.md-sidebar--secondary { display: none; }
- .md-sidebar--primary { left: 72px; width: 10rem }
+ .md-sidebar--primary { left: ${
+ isPinned ? '242px' : '72px'
+ }; width: 10rem }
.md-content { margin-left: 10rem; max-width: calc(100% - 10rem); }
.md-content__inner { font-size: 0.9rem }
.md-footer {
@@ -348,6 +354,7 @@ export const useTechDocsReaderDom = (entityRef: EntityName): Element | null => {
theme.palette.success.main,
theme.palette.text.primary,
theme.typography.fontFamily,
+ isPinned,
],
);
diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md
index 00e243d1a2..ac8b2ce957 100644
--- a/plugins/todo-backend/api-report.md
+++ b/plugins/todo-backend/api-report.md
@@ -11,38 +11,27 @@ import { Logger as Logger_2 } from 'winston';
import { ScmIntegrations } from '@backstage/integration';
import { UrlReader } from '@backstage/backend-common';
-// Warning: (ae-forgotten-export) The symbol "RouterOptions" needs to be exported by the entry point index.d.ts
-// 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)
export function createRouter(options: RouterOptions): Promise;
-// Warning: (ae-forgotten-export) The symbol "TodoParserOptions" needs to be exported by the entry point index.d.ts
-// Warning: (ae-forgotten-export) The symbol "TodoParser" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createTodoParser" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export function createTodoParser(options?: TodoParserOptions): TodoParser;
-// Warning: (ae-missing-release-tag) "ListTodosRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export type ListTodosRequest = {
entity?: EntityName;
offset?: number;
limit?: number;
orderBy?: {
- field: Fields;
+ field: 'text' | 'tag' | 'author' | 'viewUrl' | 'repoFilePath';
direction: 'asc' | 'desc';
};
filters?: {
- field: Fields;
+ field: 'text' | 'tag' | 'author' | 'viewUrl' | 'repoFilePath';
value: string;
}[];
};
-// Warning: (ae-missing-release-tag) "ListTodosResponse" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export type ListTodosResponse = {
items: TodoItem[];
@@ -51,22 +40,22 @@ export type ListTodosResponse = {
limit: number;
};
-// Warning: (ae-missing-release-tag) "ReadTodosOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export type ReadTodosOptions = {
url: string;
};
-// Warning: (ae-missing-release-tag) "ReadTodosResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export type ReadTodosResult = {
items: TodoItem[];
};
-// Warning: (ae-missing-release-tag) "TodoItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
+// @public (undocumented)
+export interface RouterOptions {
+ // (undocumented)
+ todoService: TodoService;
+}
+
// @public (undocumented)
export type TodoItem = {
text: string;
@@ -77,19 +66,36 @@ export type TodoItem = {
repoFilePath?: string;
};
-// Warning: (ae-missing-release-tag) "TodoReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
+// @public (undocumented)
+export type TodoParser = (ctx: TodoParserContext) => TodoParserResult[];
+
+// @public (undocumented)
+export type TodoParserContext = {
+ content: string;
+ path: string;
+};
+
+// @public (undocumented)
+export type TodoParserOptions = {
+ additionalTags?: string[];
+};
+
+// @public (undocumented)
+export type TodoParserResult = {
+ text: string;
+ tag: string;
+ author?: string;
+ lineNumber: number;
+};
+
// @public (undocumented)
export interface TodoReader {
readTodos(options: ReadTodosOptions): Promise;
}
-// Warning: (ae-missing-release-tag) "TodoReaderService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
export class TodoReaderService implements TodoService {
- // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts
- constructor(options: Options_2);
+ constructor(options: TodoReaderServiceOptions);
// (undocumented)
listTodos(
req: ListTodosRequest,
@@ -99,24 +105,34 @@ export class TodoReaderService implements TodoService {
): Promise;
}
-// Warning: (ae-missing-release-tag) "TodoScmReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
+// @public (undocumented)
+export type TodoReaderServiceOptions = {
+ todoReader: TodoReader;
+ catalogClient: CatalogApi;
+ maxPageSize?: number;
+ defaultPageSize?: number;
+};
+
// @public (undocumented)
export class TodoScmReader implements TodoReader {
- constructor(options: Options);
- // Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts
- //
+ constructor(options: TodoScmReaderOptions);
// (undocumented)
static fromConfig(
config: Config,
- options: Omit,
+ options: Omit,
): TodoScmReader;
// (undocumented)
readTodos(options: ReadTodosOptions): Promise;
}
-// Warning: (ae-missing-release-tag) "TodoService" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
+// @public (undocumented)
+export type TodoScmReaderOptions = {
+ logger: Logger_2;
+ reader: UrlReader;
+ integrations: ScmIntegrations;
+ parser?: TodoParser;
+};
+
// @public (undocumented)
export interface TodoService {
// (undocumented)
@@ -127,8 +143,4 @@ export interface TodoService {
},
): Promise;
}
-
-// Warnings were encountered during analysis:
-//
-// src/service/types.d.ts:9:9 - (ae-forgotten-export) The symbol "Fields" needs to be exported by the entry point index.d.ts
```
diff --git a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts
index 804dd1146d..19890a8d23 100644
--- a/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts
+++ b/plugins/todo-backend/src/lib/TodoReader/TodoScmReader.ts
@@ -41,7 +41,8 @@ const excludedExtensions = [
];
const MAX_FILE_SIZE = 200000;
-type Options = {
+/** @public */
+export type TodoScmReaderOptions = {
logger: Logger;
reader: UrlReader;
integrations: ScmIntegrations;
@@ -53,6 +54,7 @@ type CacheItem = {
result: ReadTodosResult;
};
+/** @public */
export class TodoScmReader implements TodoReader {
private readonly logger: Logger;
private readonly reader: UrlReader;
@@ -62,14 +64,17 @@ export class TodoScmReader implements TodoReader {
private readonly cache = new Map();
private readonly inFlightReads = new Map>();
- static fromConfig(config: Config, options: Omit) {
+ static fromConfig(
+ config: Config,
+ options: Omit,
+ ) {
return new TodoScmReader({
...options,
integrations: ScmIntegrations.fromConfig(config),
});
}
- constructor(options: Options) {
+ constructor(options: TodoScmReaderOptions) {
this.logger = options.logger;
this.reader = options.reader;
this.parser = options.parser ?? createTodoParser();
diff --git a/plugins/todo-backend/src/lib/TodoReader/createTodoParser.ts b/plugins/todo-backend/src/lib/TodoReader/createTodoParser.ts
index 2835f0e8d5..720efe316b 100644
--- a/plugins/todo-backend/src/lib/TodoReader/createTodoParser.ts
+++ b/plugins/todo-backend/src/lib/TodoReader/createTodoParser.ts
@@ -18,11 +18,13 @@ import { extname } from 'path';
import { parse } from 'leasot';
import { TodoParser } from './types';
+/** @public */
export type TodoParserOptions = {
/** Custom tags to support in addition to TODO and FIXME */
additionalTags?: string[];
};
+/** @public */
export function createTodoParser(options: TodoParserOptions = {}): TodoParser {
return ({ content, path }) => {
try {
diff --git a/plugins/todo-backend/src/lib/TodoReader/index.ts b/plugins/todo-backend/src/lib/TodoReader/index.ts
index aa7c36a09b..d0537861da 100644
--- a/plugins/todo-backend/src/lib/TodoReader/index.ts
+++ b/plugins/todo-backend/src/lib/TodoReader/index.ts
@@ -15,10 +15,15 @@
*/
export { TodoScmReader } from './TodoScmReader';
+export type { TodoScmReaderOptions } from './TodoScmReader';
export { createTodoParser } from './createTodoParser';
+export type { TodoParserOptions } from './createTodoParser';
export type {
TodoItem,
TodoReader,
ReadTodosOptions,
ReadTodosResult,
+ TodoParser,
+ TodoParserContext,
+ TodoParserResult,
} from './types';
diff --git a/plugins/todo-backend/src/lib/TodoReader/types.ts b/plugins/todo-backend/src/lib/TodoReader/types.ts
index 14a622b482..628a78f0c2 100644
--- a/plugins/todo-backend/src/lib/TodoReader/types.ts
+++ b/plugins/todo-backend/src/lib/TodoReader/types.ts
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+/** @public */
export type TodoItem = {
/** The contents of the TODO comment */
text: string;
@@ -34,6 +35,7 @@ export type TodoItem = {
repoFilePath?: string;
};
+/** @public */
export type ReadTodosOptions = {
/**
* Base URLs defining the root at which to search for TODOs
@@ -41,6 +43,7 @@ export type ReadTodosOptions = {
url: string;
};
+/** @public */
export type ReadTodosResult = {
/**
* TODO items found at the given locations
@@ -48,6 +51,7 @@ export type ReadTodosResult = {
items: TodoItem[];
};
+/** @public */
export interface TodoReader {
/**
* Searches for TODO items in code at a given location
@@ -55,16 +59,19 @@ export interface TodoReader {
readTodos(options: ReadTodosOptions): Promise;
}
-type TodoParserContext = {
+/** @public */
+export type TodoParserContext = {
content: string;
path: string;
};
-type TodoParserResult = {
+/** @public */
+export type TodoParserResult = {
text: string;
tag: string;
author?: string;
lineNumber: number;
};
+/** @public */
export type TodoParser = (ctx: TodoParserContext) => TodoParserResult[];
diff --git a/plugins/todo-backend/src/service/TodoReaderService.ts b/plugins/todo-backend/src/service/TodoReaderService.ts
index 6623f8090f..54957d89c4 100644
--- a/plugins/todo-backend/src/service/TodoReaderService.ts
+++ b/plugins/todo-backend/src/service/TodoReaderService.ts
@@ -29,7 +29,8 @@ import { ListTodosRequest, ListTodosResponse, TodoService } from './types';
const DEFAULT_DEFAULT_PAGE_SIZE = 10;
const DEFAULT_MAX_PAGE_SIZE = 50;
-type Options = {
+/** @public */
+export type TodoReaderServiceOptions = {
todoReader: TodoReader;
catalogClient: CatalogApi;
maxPageSize?: number;
@@ -43,13 +44,14 @@ function wildcardRegex(str: string): RegExp {
return new RegExp(`^${pattern}$`, 'i');
}
+/** @public */
export class TodoReaderService implements TodoService {
private readonly todoReader: TodoReader;
private readonly catalogClient: CatalogApi;
private readonly maxPageSize: number;
private readonly defaultPageSize: number;
- constructor(options: Options) {
+ constructor(options: TodoReaderServiceOptions) {
this.todoReader = options.todoReader;
this.catalogClient = options.catalogClient;
this.maxPageSize = options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE;
diff --git a/plugins/todo-backend/src/service/index.ts b/plugins/todo-backend/src/service/index.ts
index 893d615405..380d95dbe1 100644
--- a/plugins/todo-backend/src/service/index.ts
+++ b/plugins/todo-backend/src/service/index.ts
@@ -15,5 +15,7 @@
*/
export { createRouter } from './router';
+export type { RouterOptions } from './router';
export type { TodoService, ListTodosRequest, ListTodosResponse } from './types';
export { TodoReaderService } from './TodoReaderService';
+export type { TodoReaderServiceOptions } from './TodoReaderService';
diff --git a/plugins/todo-backend/src/service/router.ts b/plugins/todo-backend/src/service/router.ts
index 91de76e358..203e552161 100644
--- a/plugins/todo-backend/src/service/router.ts
+++ b/plugins/todo-backend/src/service/router.ts
@@ -28,10 +28,12 @@ const TODO_FIELDS = [
'repoFilePath',
] as const;
+/** @public */
export interface RouterOptions {
todoService: TodoService;
}
+/** @public */
export async function createRouter(
options: RouterOptions,
): Promise {
diff --git a/plugins/todo-backend/src/service/types.ts b/plugins/todo-backend/src/service/types.ts
index f29e0d9908..90ee6bc913 100644
--- a/plugins/todo-backend/src/service/types.ts
+++ b/plugins/todo-backend/src/service/types.ts
@@ -17,23 +17,23 @@
import { EntityName } from '@backstage/catalog-model';
import { TodoItem } from '../lib';
-type Fields = 'text' | 'tag' | 'author' | 'viewUrl' | 'repoFilePath';
-
+/** @public */
export type ListTodosRequest = {
entity?: EntityName;
offset?: number;
limit?: number;
orderBy?: {
- field: Fields;
+ field: 'text' | 'tag' | 'author' | 'viewUrl' | 'repoFilePath';
direction: 'asc' | 'desc';
};
filters?: {
- field: Fields;
+ field: 'text' | 'tag' | 'author' | 'viewUrl' | 'repoFilePath';
/** Value to filter by, with '*' used as wildcard */
value: string;
}[];
};
+/** @public */
export type ListTodosResponse = {
items: TodoItem[];
totalCount: number;
@@ -41,6 +41,7 @@ export type ListTodosResponse = {
limit: number;
};
+/** @public */
export interface TodoService {
listTodos(
req: ListTodosRequest,
diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts
index 22eae267ee..1a00ef4c5e 100644
--- a/scripts/api-extractor.ts
+++ b/scripts/api-extractor.ts
@@ -15,14 +15,15 @@
*/
/* eslint-disable import/no-extraneous-dependencies */
+/* eslint-disable no-restricted-imports */
-// eslint-disable-next-line no-restricted-imports
import {
resolve as resolvePath,
relative as relativePath,
dirname,
join,
} from 'path';
+import { spawnSync } from 'child_process';
import prettier from 'prettier';
import fs from 'fs-extra';
import {
@@ -197,6 +198,48 @@ const SKIPPED_PACKAGES = [
join('packages', 'techdocs-cli'),
];
+async function resolvePackagePath(
+ packagePath: string,
+): Promise {
+ const projectRoot = resolvePath(__dirname, '..');
+ const fullPackageDir = resolvePath(projectRoot, packagePath);
+
+ const stat = await fs.stat(fullPackageDir);
+ if (!stat.isDirectory()) {
+ return undefined;
+ }
+
+ try {
+ const packageJsonPath = join(fullPackageDir, 'package.json');
+ await fs.access(packageJsonPath);
+ } catch (_) {
+ return undefined;
+ }
+
+ return relativePath(projectRoot, fullPackageDir);
+}
+
+async function findSpecificPackageDirs(unresolvedPackageDirs: string[]) {
+ const packageDirs = new Array();
+
+ for (const unresolvedPackageDir of unresolvedPackageDirs) {
+ const packageDir = await resolvePackagePath(unresolvedPackageDir);
+ if (!packageDir) {
+ throw new Error(`'${unresolvedPackageDir}' is not a valid package path`);
+ }
+ if (SKIPPED_PACKAGES.includes(packageDir)) {
+ throw new Error(`'${packageDir}' does not have an API report`);
+ }
+ packageDirs.push(packageDir);
+ }
+
+ if (packageDirs.length === 0) {
+ return undefined;
+ }
+
+ return packageDirs;
+}
+
async function findPackageDirs() {
const packageDirs = new Array();
const projectRoot = resolvePath(__dirname, '..');
@@ -204,21 +247,11 @@ async function findPackageDirs() {
for (const packageRoot of PACKAGE_ROOTS) {
const dirs = await fs.readdir(resolvePath(projectRoot, packageRoot));
for (const dir of dirs) {
- const fullPackageDir = resolvePath(projectRoot, packageRoot, dir);
-
- const stat = await fs.stat(fullPackageDir);
- if (!stat.isDirectory()) {
+ const packageDir = await resolvePackagePath(join(packageRoot, dir));
+ if (!packageDir) {
continue;
}
- try {
- const packageJsonPath = join(fullPackageDir, 'package.json');
- await fs.access(packageJsonPath);
- } catch (_) {
- continue;
- }
-
- const packageDir = relativePath(projectRoot, fullPackageDir);
if (!SKIPPED_PACKAGES.includes(packageDir)) {
packageDirs.push(packageDir);
}
@@ -228,6 +261,26 @@ async function findPackageDirs() {
return packageDirs;
}
+async function createTemporaryTsConfig(includedPackageDirs: string[]) {
+ const path = resolvePath(__dirname, '..', 'tsconfig.tmp.json');
+
+ process.once('exit', () => {
+ fs.removeSync(path);
+ });
+
+ await fs.writeJson(path, {
+ extends: './tsconfig.json',
+ include: [
+ // These two contain global definitions that are needed for stable API report generation
+ 'packages/cli/asset-types/asset-types.d.ts',
+ 'node_modules/handlebars/types/index.d.ts',
+ ...includedPackageDirs.map(dir => join(dir, 'src')),
+ ],
+ });
+
+ return path;
+}
+
async function getTsDocConfig() {
const tsdocConfigFile = await TSDocConfigFile.loadFile(
require.resolve('@microsoft/api-extractor/extends/tsdoc-base.json'),
@@ -261,12 +314,14 @@ interface ApiExtractionOptions {
packageDirs: string[];
outputDir: string;
isLocalBuild: boolean;
+ tsconfigFilePath: string;
}
async function runApiExtraction({
packageDirs,
outputDir,
isLocalBuild,
+ tsconfigFilePath,
}: ApiExtractionOptions) {
await fs.remove(outputDir);
@@ -287,7 +342,7 @@ async function runApiExtraction({
bundledPackages: [],
compiler: {
- tsconfigFilePath: resolvePath(__dirname, '../tsconfig.json'),
+ tsconfigFilePath,
},
apiReport: {
@@ -663,23 +718,71 @@ async function buildDocs({
}
async function main() {
+ const projectRoot = resolvePath(__dirname, '..');
const isCiBuild = process.argv.includes('--ci');
const isDocsBuild = process.argv.includes('--docs');
+ const runTsc = process.argv.includes('--tsc');
- const packageDirs = await findPackageDirs();
+ const selectedPackageDirs = await findSpecificPackageDirs(
+ process.argv.slice(2).filter(arg => !arg.startsWith('--')),
+ );
+ if (selectedPackageDirs && (isCiBuild || isDocsBuild)) {
+ throw new Error(
+ 'Package path arguments are not supported for the --ci and --docs flags',
+ );
+ }
+ if (!selectedPackageDirs && !isCiBuild && !isDocsBuild) {
+ console.log('');
+ console.log(
+ 'TIP: You can generate api-reports for select packages by passing package paths:',
+ );
+ console.log('');
+ console.log(
+ ' yarn build:api-reports packages/config packages/core-plugin-api',
+ );
+ console.log('');
+ }
+
+ let temporaryTsConfigPath: string | undefined;
+ if (selectedPackageDirs) {
+ temporaryTsConfigPath = await createTemporaryTsConfig(selectedPackageDirs);
+ }
+ const tsconfigFilePath =
+ temporaryTsConfigPath ?? resolvePath(projectRoot, 'tsconfig.json');
+
+ if (runTsc) {
+ await fs.remove(resolvePath(projectRoot, 'dist-types'));
+ spawnSync(
+ 'yarn',
+ [
+ 'tsc',
+ ['--project', tsconfigFilePath],
+ ['--skipLibCheck', 'false'],
+ ['--incremental', 'false'],
+ ].flat(),
+ {
+ stdio: 'inherit',
+ shell: true,
+ cwd: projectRoot,
+ },
+ );
+ }
+
+ const packageDirs = selectedPackageDirs ?? (await findPackageDirs());
console.log('# Generating package API reports');
await runApiExtraction({
packageDirs,
outputDir: tmpDir,
isLocalBuild: !isCiBuild,
+ tsconfigFilePath,
});
if (isDocsBuild) {
console.log('# Generating package documentation');
await buildDocs({
inputDir: tmpDir,
- outputDir: resolvePath(__dirname, '..', 'docs/reference'),
+ outputDir: resolvePath(projectRoot, 'docs/reference'),
});
}
}
diff --git a/yarn.lock b/yarn.lock
index 7570e7b624..ada84af89b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -331,26 +331,12 @@
dependencies:
"@babel/highlight" "^7.10.4"
-"@babel/code-frame@7.12.11":
- version "7.12.11"
- resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
- integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
+ integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
dependencies:
- "@babel/highlight" "^7.10.4"
-
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.5.5":
- version "7.12.13"
- resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
- integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==
- dependencies:
- "@babel/highlight" "^7.12.13"
-
-"@babel/code-frame@^7.14.5", "@babel/code-frame@^7.8.3":
- version "7.14.5"
- resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb"
- integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==
- dependencies:
- "@babel/highlight" "^7.14.5"
+ "@babel/highlight" "^7.16.7"
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.4":
version "7.14.4"
@@ -362,6 +348,11 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.9.tgz#ac7996ceaafcf8f410119c8af0d1db4cf914a210"
integrity sha512-p3QjZmMGHDGdpcwEYYWu7i7oJShJvtgMjJeb0W95PPhSm++3lm8YXYOh45Y6iCN9PkZLTZ7CIX5nFrp7pw7TXw==
+"@babel/compat-data@^7.16.4":
+ version "7.16.4"
+ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e"
+ integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==
+
"@babel/core@7.12.9":
version "7.12.9"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8"
@@ -384,7 +375,7 @@
semver "^5.4.1"
source-map "^0.5.0"
-"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.7.5":
+"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.7.5":
version "7.14.8"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010"
integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==
@@ -405,6 +396,27 @@
semver "^6.3.0"
source-map "^0.5.0"
+"@babel/core@^7.14.0":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf"
+ integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.16.7"
+ "@babel/helper-compilation-targets" "^7.16.7"
+ "@babel/helper-module-transforms" "^7.16.7"
+ "@babel/helpers" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.1.2"
+ semver "^6.3.0"
+ source-map "^0.5.0"
+
"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.14.8", "@babel/generator@^7.14.9":
version "7.14.9"
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.14.9.tgz#23b19c597d38b4f7dc2e3fe42a69c88d9ecfaa16"
@@ -414,7 +426,16 @@
jsesc "^2.5.1"
source-map "^0.5.0"
-"@babel/generator@^7.12.13", "@babel/generator@^7.14.2", "@babel/generator@^7.5.0":
+"@babel/generator@^7.14.0", "@babel/generator@^7.16.0", "@babel/generator@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz#b42bf46a3079fa65e1544135f32e7958f048adbb"
+ integrity sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+ jsesc "^2.5.1"
+ source-map "^0.5.0"
+
+"@babel/generator@^7.14.2":
version "7.14.3"
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz#0c2652d91f7bddab7cccc6ba8157e4f40dcedb91"
integrity sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==
@@ -473,6 +494,16 @@
browserslist "^4.16.6"
semver "^6.3.0"
+"@babel/helper-compilation-targets@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b"
+ integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==
+ dependencies:
+ "@babel/compat-data" "^7.16.4"
+ "@babel/helper-validator-option" "^7.16.7"
+ browserslist "^4.17.5"
+ semver "^6.3.0"
+
"@babel/helper-create-class-features-plugin@^7.13.0", "@babel/helper-create-class-features-plugin@^7.14.0", "@babel/helper-create-class-features-plugin@^7.14.3":
version "7.14.4"
resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.4.tgz#abf888d836a441abee783c75229279748705dc42"
@@ -541,6 +572,13 @@
resolve "^1.14.2"
semver "^6.1.2"
+"@babel/helper-environment-visitor@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7"
+ integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-explode-assignable-expression@^7.12.13":
version "7.13.0"
resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.13.0.tgz#17b5c59ff473d9f956f40ef570cf3a76ca12657f"
@@ -573,6 +611,15 @@
"@babel/template" "^7.14.5"
"@babel/types" "^7.14.5"
+"@babel/helper-function-name@^7.16.0", "@babel/helper-function-name@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f"
+ integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
"@babel/helper-get-function-arity@^7.12.13":
version "7.12.13"
resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583"
@@ -587,6 +634,13 @@
dependencies:
"@babel/types" "^7.14.5"
+"@babel/helper-get-function-arity@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
+ integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-hoist-variables@^7.13.0":
version "7.13.16"
resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.13.16.tgz#1b1651249e94b51f8f0d33439843e33e39775b30"
@@ -602,6 +656,13 @@
dependencies:
"@babel/types" "^7.14.5"
+"@babel/helper-hoist-variables@^7.16.0", "@babel/helper-hoist-variables@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246"
+ integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-member-expression-to-functions@^7.13.12":
version "7.13.12"
resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72"
@@ -630,6 +691,13 @@
dependencies:
"@babel/types" "^7.14.5"
+"@babel/helper-module-imports@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437"
+ integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.14.8":
version "7.14.8"
resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz#d4279f7e3fd5f4d5d342d833af36d4dd87d7dc49"
@@ -658,6 +726,20 @@
"@babel/traverse" "^7.14.2"
"@babel/types" "^7.14.2"
+"@babel/helper-module-transforms@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41"
+ integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-simple-access" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/helper-validator-identifier" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
"@babel/helper-optimise-call-expression@^7.12.13":
version "7.12.13"
resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea"
@@ -739,6 +821,13 @@
dependencies:
"@babel/types" "^7.14.8"
+"@babel/helper-simple-access@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7"
+ integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
"@babel/helper-skip-transparent-expression-wrappers@^7.12.1":
version "7.12.1"
resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf"
@@ -767,15 +856,17 @@
dependencies:
"@babel/types" "^7.14.5"
-"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0":
- version "7.14.0"
- resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
- integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==
+"@babel/helper-split-export-declaration@^7.16.0", "@babel/helper-split-export-declaration@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b"
+ integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
+ dependencies:
+ "@babel/types" "^7.16.7"
-"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8", "@babel/helper-validator-identifier@^7.14.9":
- version "7.14.9"
- resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
- integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
+"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.14.0", "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.8", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7", "@babel/helper-validator-identifier@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
+ integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
"@babel/helper-validator-option@^7.12.17":
version "7.12.17"
@@ -787,6 +878,11 @@
resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
+"@babel/helper-validator-option@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
+ integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==
+
"@babel/helper-wrap-function@^7.13.0":
version "7.13.0"
resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.13.0.tgz#bdb5c66fda8526ec235ab894ad53a1235c79fcc4"
@@ -816,34 +912,39 @@
"@babel/traverse" "^7.14.8"
"@babel/types" "^7.14.8"
-"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13":
- version "7.14.0"
- resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz#3197e375711ef6bf834e67d0daec88e4f46113cf"
- integrity sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==
+"@babel/helpers@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc"
+ integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==
dependencies:
- "@babel/helper-validator-identifier" "^7.14.0"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
+"@babel/highlight@^7.0.0", "@babel/highlight@^7.10.4", "@babel/highlight@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b"
+ integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/highlight@^7.14.5":
- version "7.14.5"
- resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
- integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
- dependencies:
- "@babel/helper-validator-identifier" "^7.14.5"
- chalk "^2.0.0"
- js-tokens "^4.0.0"
+"@babel/parser@7.16.4":
+ version "7.16.4"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e"
+ integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==
-"@babel/parser@7.12.16":
- version "7.12.16"
- resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4"
- integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw==
-
-"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.13", "@babel/parser@^7.12.7", "@babel/parser@^7.13.16", "@babel/parser@^7.14.2", "@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.14.9":
+"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.13", "@babel/parser@^7.12.7", "@babel/parser@^7.13.16", "@babel/parser@^7.14.2", "@babel/parser@^7.14.5", "@babel/parser@^7.14.8", "@babel/parser@^7.14.9":
version "7.14.9"
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.14.9.tgz#596c1ad67608070058ebf8df50c1eaf65db895a4"
integrity sha512-RdUTOseXJ8POjjOeEBEvNMIZU/nm4yu2rufRkcibzkkg7DmQvXU8v3M4Xk9G7uuI86CDGkKcuDWgioqZm+mScQ==
+"@babel/parser@^7.14.0", "@babel/parser@^7.16.3", "@babel/parser@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz#d372dda9c89fcec340a82630a9f533f2fe15877e"
+ integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA==
+
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12":
version "7.13.12"
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.13.12.tgz#a3484d84d0b549f3fc916b99ee4783f26fabad2a"
@@ -2080,13 +2181,20 @@
core-js-pure "^3.16.0"
regenerator-runtime "^0.13.4"
-"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.6", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.6", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.16.3"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5"
integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==
dependencies:
regenerator-runtime "^0.13.4"
+"@babel/runtime@^7.16.3":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa"
+ integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
"@babel/template@^7.12.13", "@babel/template@^7.3.3":
version "7.12.13"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
@@ -2105,22 +2213,31 @@
"@babel/parser" "^7.14.5"
"@babel/types" "^7.14.5"
-"@babel/traverse@7.12.13":
- version "7.12.13"
- resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0"
- integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA==
+"@babel/template@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
+ integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
dependencies:
- "@babel/code-frame" "^7.12.13"
- "@babel/generator" "^7.12.13"
- "@babel/helper-function-name" "^7.12.13"
- "@babel/helper-split-export-declaration" "^7.12.13"
- "@babel/parser" "^7.12.13"
- "@babel/types" "^7.12.13"
+ "@babel/code-frame" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
+"@babel/traverse@7.16.3":
+ version "7.16.3"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz#f63e8a938cc1b780f66d9ed3c54f532ca2d14787"
+ integrity sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==
+ dependencies:
+ "@babel/code-frame" "^7.16.0"
+ "@babel/generator" "^7.16.0"
+ "@babel/helper-function-name" "^7.16.0"
+ "@babel/helper-hoist-variables" "^7.16.0"
+ "@babel/helper-split-export-declaration" "^7.16.0"
+ "@babel/parser" "^7.16.3"
+ "@babel/types" "^7.16.0"
debug "^4.1.0"
globals "^11.1.0"
- lodash "^4.17.19"
-"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.2", "@babel/traverse@^7.4.5":
+"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.2", "@babel/traverse@^7.4.5":
version "7.14.2"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b"
integrity sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==
@@ -2149,13 +2266,28 @@
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@7.12.13":
- version "7.12.13"
- resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611"
- integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ==
+"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz#dac01236a72c2560073658dd1a285fe4e0865d76"
+ integrity sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ==
dependencies:
- "@babel/helper-validator-identifier" "^7.12.11"
- lodash "^4.17.19"
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.16.7"
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-function-name" "^7.16.7"
+ "@babel/helper-hoist-variables" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/types" "^7.16.7"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@7.16.0":
+ version "7.16.0"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba"
+ integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.15.7"
to-fast-properties "^2.0.0"
"@babel/types@^7.0.0", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.13.0", "@babel/types@^7.13.12", "@babel/types@^7.13.16", "@babel/types@^7.14.2", "@babel/types@^7.14.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
@@ -2174,6 +2306,14 @@
"@babel/helper-validator-identifier" "^7.14.9"
to-fast-properties "^2.0.0"
+"@babel/types@^7.16.0", "@babel/types@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz#4ed19d51f840ed4bd5645be6ce40775fecf03159"
+ integrity sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ to-fast-properties "^2.0.0"
+
"@bcoe/v8-coverage@^0.2.3":
version "0.2.3"
resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@@ -2664,18 +2804,18 @@
ts-node "^9"
tslib "^2"
-"@eslint/eslintrc@^0.4.2":
- version "0.4.2"
- resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"
- integrity sha512-8nmGq/4ycLpIwzvhI4tNDmQztZ8sp+hI7cyG8i1nQDhkAbRzHpXPidRAHlNvCZQpJTKw5ItIpMw9RSToGF00mg==
+"@eslint/eslintrc@^1.0.5":
+ version "1.0.5"
+ resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318"
+ integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==
dependencies:
ajv "^6.12.4"
- debug "^4.1.1"
- espree "^7.3.0"
+ debug "^4.3.2"
+ espree "^9.2.0"
globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
- js-yaml "^3.13.1"
+ js-yaml "^4.1.0"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
@@ -2807,23 +2947,23 @@
"@n1ru4l/push-pull-async-iterable-iterator" "^3.1.0"
meros "^1.1.4"
-"@graphql-codegen/cli@^1.21.3":
- version "1.21.6"
- resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.6.tgz#d06b5f6cb625541f3981d69f99966e520b958072"
- integrity sha512-wtBk4lk/YxG6MrxnBOxE9nCfR9PNDjaqA8CF9hi6Q8jiSl4sV03tC2R+gE7+2EI8J6Xa1bxZe15LnBhVwb/mUA==
+"@graphql-codegen/cli@^2.3.1":
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-2.3.1.tgz#66083293b60e3182603d70031210d59e6f1a16e5"
+ integrity sha512-xMSvYqFtnRXOp/sVJSyqiFTm70X8ouLXiq5o/R/D3yQtA6NNudAC+Q4oxg9/LZKnRDL6pehwdC8CNnQk0Tf7Sw==
dependencies:
- "@graphql-codegen/core" "1.17.10"
- "@graphql-codegen/plugin-helpers" "^1.18.7"
- "@graphql-tools/apollo-engine-loader" "^6.2.5"
- "@graphql-tools/code-file-loader" "^6.3.1"
- "@graphql-tools/git-loader" "^6.2.6"
- "@graphql-tools/github-loader" "^6.2.5"
- "@graphql-tools/graphql-file-loader" "^6.2.7"
- "@graphql-tools/json-file-loader" "^6.2.6"
- "@graphql-tools/load" "^6.2.8"
- "@graphql-tools/prisma-loader" "^6.3.0"
- "@graphql-tools/url-loader" "^6.10.1"
- "@graphql-tools/utils" "^7.9.1"
+ "@graphql-codegen/core" "2.4.0"
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
+ "@graphql-tools/apollo-engine-loader" "^7.0.5"
+ "@graphql-tools/code-file-loader" "^7.0.6"
+ "@graphql-tools/git-loader" "^7.0.5"
+ "@graphql-tools/github-loader" "^7.0.5"
+ "@graphql-tools/graphql-file-loader" "^7.0.5"
+ "@graphql-tools/json-file-loader" "^7.1.2"
+ "@graphql-tools/load" "^7.3.0"
+ "@graphql-tools/prisma-loader" "^7.0.6"
+ "@graphql-tools/url-loader" "^7.0.11"
+ "@graphql-tools/utils" "^8.1.1"
ansi-escapes "^4.3.1"
chalk "^4.1.0"
change-case-all "1.0.14"
@@ -2834,8 +2974,9 @@
dependency-graph "^0.11.0"
detect-indent "^6.0.0"
glob "^7.1.6"
- graphql-config "^3.3.0"
- inquirer "^7.3.3"
+ globby "^11.0.4"
+ graphql-config "^4.1.0"
+ inquirer "^8.0.0"
is-glob "^4.0.1"
json-to-pretty-yaml "^1.2.2"
latest-version "5.1.0"
@@ -2852,74 +2993,69 @@
yaml "^1.10.0"
yargs "^17.0.0"
-"@graphql-codegen/core@1.17.10":
- version "1.17.10"
- resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-1.17.10.tgz#3b85b5bc2e84fcacbd25fced5af47a4bb2d7a8bd"
- integrity sha512-RA3umgVDs/RI/+ztHh+H4GfJxrJUfWJQqoAkMfX4qPTVO5qsy3R4vPudE0oP8w+kFbL8dFsRfAAPUZxI4jV/hQ==
+"@graphql-codegen/core@2.4.0":
+ version "2.4.0"
+ resolved "https://registry.npmjs.org/@graphql-codegen/core/-/core-2.4.0.tgz#d94dcc088b5e117c847ce5b10c4fe1eb7325e180"
+ integrity sha512-5RiYE1+07jayp/3w/bkyaCXtfKNeKmRabpPP4aRi369WeH2cH37l2K8NbhkIU+zhpnhoqMID61TO56x2fKldZQ==
dependencies:
- "@graphql-codegen/plugin-helpers" "^1.18.7"
- "@graphql-tools/merge" "^6.2.14"
- "@graphql-tools/utils" "^7.9.1"
- tslib "~2.2.0"
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
+ "@graphql-tools/schema" "^8.1.2"
+ "@graphql-tools/utils" "^8.1.1"
+ tslib "~2.3.0"
-"@graphql-codegen/plugin-helpers@^1.18.7", "@graphql-codegen/plugin-helpers@^1.18.8":
- version "1.18.8"
- resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-1.18.8.tgz#39aac745b9e22e28c781cc07cf74836896a3a905"
- integrity sha512-mb4I9j9lMGqvGggYuZ0CV+Hme08nar68xkpPbAVotg/ZBmlhZIok/HqW2BcMQi7Rj+Il5HQMeQ1wQ1M7sv/TlQ==
+"@graphql-codegen/plugin-helpers@^2.3.2":
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.3.2.tgz#3f9ba625791901d19be733db1dfc9a3dbd0dac44"
+ integrity sha512-19qFA5XMAWaAY64sBljjDPYfHjE+QMk/+oalCyY13WjSlcLDvYPfmFlCNgFSsydArDELlHR8T1GMbA7C42M8TA==
dependencies:
- "@graphql-tools/utils" "^7.9.1"
- common-tags "1.8.0"
+ "@graphql-tools/utils" "^8.5.2"
+ change-case-all "1.0.14"
+ common-tags "1.8.2"
import-from "4.0.0"
lodash "~4.17.0"
tslib "~2.3.0"
-"@graphql-codegen/typescript-resolvers@^1.17.7":
- version "1.19.3"
- resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-1.19.3.tgz#9e5215bdc202350c4cb54d866f9f26d1e458d81b"
- integrity sha512-wbc3hgULs7/gmlmVvbUpqxoOff2MjVnSvBllrldBIezGvcoj7Q265Cb0q/ki5MV8OzUWq28zpBrc3RMg7E5O9Q==
+"@graphql-codegen/schema-ast@^2.4.1":
+ version "2.4.1"
+ resolved "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-2.4.1.tgz#ad742b53e32f7a2fbff8ea8a91ba7e617e6ef236"
+ integrity sha512-bIWlKk/ShoVJfghA4Rt1OWnd34/dQmZM/vAe6fu6QKyOh44aAdqPtYQ2dbTyFXoknmu504etKJGEDllYNUJRfg==
dependencies:
- "@graphql-codegen/plugin-helpers" "^1.18.7"
- "@graphql-codegen/typescript" "^1.22.2"
- "@graphql-codegen/visitor-plugin-common" "1.21.1"
- "@graphql-tools/utils" "^7.9.1"
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
+ "@graphql-tools/utils" "^8.1.1"
+ tslib "~2.3.0"
+
+"@graphql-codegen/typescript-resolvers@^2.4.2":
+ version "2.4.3"
+ resolved "https://registry.npmjs.org/@graphql-codegen/typescript-resolvers/-/typescript-resolvers-2.4.3.tgz#556dbaf23eac0ff9c321d3ce7126d96a839f793f"
+ integrity sha512-4m3E0zKLSXjGirZcYHHaZ0bxjy/gxvuumShFCKFmYTkHwTfqBaeh/pMhWqLkwC9wimrH6mQoPIYSQHLaF6Eqng==
+ dependencies:
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
+ "@graphql-codegen/typescript" "^2.4.2"
+ "@graphql-codegen/visitor-plugin-common" "2.5.2"
+ "@graphql-tools/utils" "^8.1.1"
auto-bind "~4.0.0"
tslib "~2.3.0"
-"@graphql-codegen/typescript@^1.17.7", "@graphql-codegen/typescript@^1.22.2":
- version "1.23.0"
- resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-1.23.0.tgz#48a5372bcbe81a442c71c1bb032c312c6586a59a"
- integrity sha512-ZfFgk5mGfuOy4kEpy+dcuvJMphigMfJ4AkiP1qWmWFufDW3Sg2yayTSNmzeFdcXMrWGgfNW2dKtuuTmbmQhS5g==
+"@graphql-codegen/typescript@^2.4.2":
+ version "2.4.2"
+ resolved "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-2.4.2.tgz#a239d5fd8f11140d5d4c81cfae7ff02054b724dc"
+ integrity sha512-8ajWidiFqF1KNAywtb/692SjwTyjzrDHo1sf2Q7Z+rh9qDEIrh83VHB8naT/1CefOvxj3MS6GbcsvJMizaE/AQ==
dependencies:
- "@graphql-codegen/plugin-helpers" "^1.18.8"
- "@graphql-codegen/visitor-plugin-common" "1.22.0"
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
+ "@graphql-codegen/schema-ast" "^2.4.1"
+ "@graphql-codegen/visitor-plugin-common" "2.5.2"
auto-bind "~4.0.0"
tslib "~2.3.0"
-"@graphql-codegen/visitor-plugin-common@1.21.1":
- version "1.21.1"
- resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.21.1.tgz#d080265e42c2a8867520b29baf283b1e1012bbb8"
- integrity sha512-f6GakFkn6TEtuU//BrZfmdL5eyzlisE8x6LmNJvjPQig8pVBVt8ncJeWV42XV9iJpaCmrQaT4MtXPkjlCe0egA==
+"@graphql-codegen/visitor-plugin-common@2.5.2":
+ version "2.5.2"
+ resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.5.2.tgz#90aa4add41e17bca83f1c7c8ad674f2a06065efd"
+ integrity sha512-qDMraPmumG+vEGAz42/asRkdgIRmQWH5HTc320UX+I6CY6eE/Ey85cgzoqeQGLV8gu4sj3UkNx/3/r79eX4u+Q==
dependencies:
- "@graphql-codegen/plugin-helpers" "^1.18.7"
+ "@graphql-codegen/plugin-helpers" "^2.3.2"
"@graphql-tools/optimize" "^1.0.1"
- "@graphql-tools/relay-operation-optimizer" "^6.3.0"
- array.prototype.flatmap "^1.2.4"
- auto-bind "~4.0.0"
- change-case-all "1.0.14"
- dependency-graph "^0.11.0"
- graphql-tag "^2.11.0"
- parse-filepath "^1.0.2"
- tslib "~2.3.0"
-
-"@graphql-codegen/visitor-plugin-common@1.22.0":
- version "1.22.0"
- resolved "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-1.22.0.tgz#75fc8b580143bccbec411eb92d5fef715ed22e42"
- integrity sha512-2afJGb6d8iuZl9KizYsexPwraEKO1lAvt5eVHNM5Xew4vwz/AUHeqDR2uOeQgVV+27EzjjzSDd47IEdH0dLC2w==
- dependencies:
- "@graphql-codegen/plugin-helpers" "^1.18.8"
- "@graphql-tools/optimize" "^1.0.1"
- "@graphql-tools/relay-operation-optimizer" "^6.3.0"
- array.prototype.flatmap "^1.2.4"
+ "@graphql-tools/relay-operation-optimizer" "^6.3.7"
+ "@graphql-tools/utils" "^8.3.0"
auto-bind "~4.0.0"
change-case-all "1.0.14"
dependency-graph "^0.11.0"
@@ -2968,14 +3104,15 @@
graphql-tools "5.0.0"
tslib "1.11.1"
-"@graphql-tools/apollo-engine-loader@^6.2.5":
- version "6.2.5"
- resolved "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-6.2.5.tgz#b9e65744f522bb9f6ca50651e5622820c4f059a8"
- integrity sha512-CE4uef6PyxtSG+7OnLklIr2BZZDgjO89ZXK47EKdY7jQy/BQD/9o+8SxPsgiBc+2NsDJH2I6P/nqoaJMOEat6g==
+"@graphql-tools/apollo-engine-loader@^7.0.5":
+ version "7.2.1"
+ resolved "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.2.1.tgz#14e5d0b1032a7d882d22a7533c8969ee3fa797f2"
+ integrity sha512-Fj/A8+9SXPTXkpKqhcSq7O9WZuMdy5zynGrnMyewbCuw1kSfzgC4pJB76ILSPa5ajOcC5bBmmvXm+yVFVRgVMg==
dependencies:
- "@graphql-tools/utils" "^7.0.0"
- cross-fetch "3.0.6"
- tslib "~2.0.1"
+ "@graphql-tools/utils" "^8.5.1"
+ cross-undici-fetch "^0.0.20"
+ sync-fetch "0.3.1"
+ tslib "~2.3.0"
"@graphql-tools/batch-execute@^7.1.2":
version "7.1.2"
@@ -2997,14 +3134,16 @@
tslib "~2.3.0"
value-or-promise "1.0.11"
-"@graphql-tools/code-file-loader@^6.3.1":
- version "6.3.1"
- resolved "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-6.3.1.tgz#42dfd4db5b968acdb453382f172ec684fa0c34ed"
- integrity sha512-ZJimcm2ig+avgsEOWWVvAaxZrXXhiiSZyYYOJi0hk9wh5BxZcLUNKkTp6EFnZE/jmGUwuos3pIjUD3Hwi3Bwhg==
+"@graphql-tools/code-file-loader@^7.0.6":
+ version "7.2.3"
+ resolved "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-7.2.3.tgz#b53e8809528da07911423c3a511e5fccf9121a12"
+ integrity sha512-aNVG3/VG5cUpS389rpCum+z7RY98qvPwOzd+J4LVr+f5hWQbDREnSFM+5RVTDfULujrsi7edKaGxGKp68pGmAA==
dependencies:
- "@graphql-tools/graphql-tag-pluck" "^6.5.1"
- "@graphql-tools/utils" "^7.0.0"
- tslib "~2.1.0"
+ "@graphql-tools/graphql-tag-pluck" "^7.1.3"
+ "@graphql-tools/utils" "^8.5.1"
+ globby "^11.0.3"
+ tslib "~2.3.0"
+ unixify "^1.0.0"
"@graphql-tools/delegate@^7.0.1", "@graphql-tools/delegate@^7.1.5":
version "7.1.5"
@@ -3031,26 +3170,30 @@
tslib "~2.3.0"
value-or-promise "1.0.11"
-"@graphql-tools/git-loader@^6.2.6":
- version "6.2.6"
- resolved "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-6.2.6.tgz#c2226f4b8f51f1c05c9ab2649ba32d49c68cd077"
- integrity sha512-ooQTt2CaG47vEYPP3CPD+nbA0F+FYQXfzrB1Y1ABN9K3d3O2RK3g8qwslzZaI8VJQthvKwt0A95ZeE4XxteYfw==
+"@graphql-tools/git-loader@^7.0.5":
+ version "7.1.2"
+ resolved "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-7.1.2.tgz#7a7b5fc366bcc9e2e14e0463ff73f1a19aafabbd"
+ integrity sha512-vIMrISQPKQgHS893b8K/pEE1InPV+7etzFhHoyQRhYkVHXP2RBkfI64Wq9bNPezF8Ss/dwIjI/keLaPp9EQDmA==
dependencies:
- "@graphql-tools/graphql-tag-pluck" "^6.2.6"
- "@graphql-tools/utils" "^7.0.0"
- tslib "~2.1.0"
+ "@graphql-tools/graphql-tag-pluck" "^7.1.3"
+ "@graphql-tools/utils" "^8.5.1"
+ is-glob "4.0.3"
+ micromatch "^4.0.4"
+ tslib "~2.3.0"
+ unixify "^1.0.0"
-"@graphql-tools/github-loader@^6.2.5":
- version "6.2.5"
- resolved "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-6.2.5.tgz#460dff6f5bbaa26957a5ea3be4f452b89cc6a44b"
- integrity sha512-DLuQmYeNNdPo8oWus8EePxWCfCAyUXPZ/p1PWqjrX/NGPyH2ZObdqtDAfRHztljt0F/qkBHbGHCEk2TKbRZTRw==
+"@graphql-tools/github-loader@^7.0.5":
+ version "7.2.1"
+ resolved "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-7.2.1.tgz#53ce2bf215a0eb083ff985b213402a24f1302da2"
+ integrity sha512-vqwh2H11ZkAATDam/JqiP0CSqQRPUbjgCDxPdUu/xvST2QKyA4+uVXLBcpBRJc5kJCQjELijeRWVHSk9oN1q6g==
dependencies:
- "@graphql-tools/graphql-tag-pluck" "^6.2.6"
- "@graphql-tools/utils" "^7.0.0"
- cross-fetch "3.0.6"
- tslib "~2.0.1"
+ "@graphql-tools/graphql-tag-pluck" "^7.1.3"
+ "@graphql-tools/utils" "^8.5.1"
+ cross-undici-fetch "^0.0.20"
+ sync-fetch "0.3.1"
+ tslib "~2.3.0"
-"@graphql-tools/graphql-file-loader@^6.0.0", "@graphql-tools/graphql-file-loader@^6.2.7":
+"@graphql-tools/graphql-file-loader@^6.0.0":
version "6.2.7"
resolved "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-6.2.7.tgz#d3720f2c4f4bb90eb2a03a7869a780c61945e143"
integrity sha512-5k2SNz0W87tDcymhEMZMkd6/vs6QawDyjQXWtqkuLTBF3vxjxPD1I4dwHoxgWPIjjANhXybvulD7E+St/7s9TQ==
@@ -3059,7 +3202,7 @@
"@graphql-tools/utils" "^7.0.0"
tslib "~2.1.0"
-"@graphql-tools/graphql-file-loader@^7.3.2":
+"@graphql-tools/graphql-file-loader@^7.0.5", "@graphql-tools/graphql-file-loader@^7.3.2":
version "7.3.3"
resolved "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.3.3.tgz#7cee2f84f08dc13fa756820b510248b857583d36"
integrity sha512-6kUJZiNpYKVhum9E5wfl5PyLLupEDYdH7c8l6oMrk6c7EPEVs6iSUyB7yQoWrtJccJLULBW2CRQ5IHp5JYK0mA==
@@ -3070,16 +3213,16 @@
tslib "~2.3.0"
unixify "^1.0.0"
-"@graphql-tools/graphql-tag-pluck@^6.2.6", "@graphql-tools/graphql-tag-pluck@^6.5.1":
- version "6.5.1"
- resolved "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-6.5.1.tgz#5fb227dbb1e19f4b037792b50f646f16a2d4c686"
- integrity sha512-7qkm82iFmcpb8M6/yRgzjShtW6Qu2OlCSZp8uatA3J0eMl87TxyJoUmL3M3UMMOSundAK8GmoyNVFUrueueV5Q==
+"@graphql-tools/graphql-tag-pluck@^7.1.3":
+ version "7.1.4"
+ resolved "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.1.4.tgz#174b69d40988c3450d310173c5be5af894929c41"
+ integrity sha512-0V2AY68ip3YmJ9rnIwQGxXsokCeGD9FTQOeSLzpwG74U0VY6bphfaCp5KVGW+W5sGJchTj3HvnmvdmWZnEZWZA==
dependencies:
- "@babel/parser" "7.12.16"
- "@babel/traverse" "7.12.13"
- "@babel/types" "7.12.13"
- "@graphql-tools/utils" "^7.0.0"
- tslib "~2.1.0"
+ "@babel/parser" "7.16.4"
+ "@babel/traverse" "7.16.3"
+ "@babel/types" "7.16.0"
+ "@graphql-tools/utils" "^8.5.1"
+ tslib "~2.3.0"
"@graphql-tools/import@^6.2.6":
version "6.3.1"
@@ -3098,7 +3241,7 @@
resolve-from "5.0.0"
tslib "~2.3.0"
-"@graphql-tools/json-file-loader@^6.0.0", "@graphql-tools/json-file-loader@^6.2.6":
+"@graphql-tools/json-file-loader@^6.0.0":
version "6.2.6"
resolved "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-6.2.6.tgz#830482cfd3721a0799cbf2fe5b09959d9332739a"
integrity sha512-CnfwBSY5926zyb6fkDBHnlTblHnHI4hoBALFYXnrg0Ev4yWU8B04DZl/pBRUc459VNgO2x8/mxGIZj2hPJG1EA==
@@ -3106,7 +3249,7 @@
"@graphql-tools/utils" "^7.0.0"
tslib "~2.0.1"
-"@graphql-tools/json-file-loader@^7.3.2":
+"@graphql-tools/json-file-loader@^7.1.2", "@graphql-tools/json-file-loader@^7.3.2":
version "7.3.3"
resolved "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-7.3.3.tgz#45cfde77b9dc4ab6c21575305ae537d2814d237f"
integrity sha512-CN2Qk9rt+Gepa3rb3X/mpxYA5MIYLwZBPj2Njw6lbZ6AaxG+O1ArDCL5ACoiWiBimn1FCOM778uhRM9znd0b3Q==
@@ -3116,7 +3259,7 @@
tslib "~2.3.0"
unixify "^1.0.0"
-"@graphql-tools/load@^6.0.0", "@graphql-tools/load@^6.2.8":
+"@graphql-tools/load@^6.0.0":
version "6.2.8"
resolved "https://registry.npmjs.org/@graphql-tools/load/-/load-6.2.8.tgz#16900fb6e75e1d075cad8f7ea439b334feb0b96a"
integrity sha512-JpbyXOXd8fJXdBh2ta0Q4w8ia6uK5FHzrTNmcvYBvflFuWly2LDTk2abbSl81zKkzswQMEd2UIYghXELRg8eTA==
@@ -3131,6 +3274,16 @@
unixify "1.0.0"
valid-url "1.0.9"
+"@graphql-tools/load@^7.3.0":
+ version "7.5.1"
+ resolved "https://registry.npmjs.org/@graphql-tools/load/-/load-7.5.1.tgz#8c7f846d2185ddc1d44fdfbf1ed9cb678f69e40b"
+ integrity sha512-j9XcLYZPZdl/TzzqA83qveJmwcCxgGizt5L1+C1/Z68brTEmQHLdQCOR3Ma3ewESJt6DU05kSTu2raKaunkjRg==
+ dependencies:
+ "@graphql-tools/schema" "8.3.1"
+ "@graphql-tools/utils" "^8.6.0"
+ p-limit "3.1.0"
+ tslib "~2.3.0"
+
"@graphql-tools/load@^7.4.1":
version "7.4.1"
resolved "https://registry.npmjs.org/@graphql-tools/load/-/load-7.4.1.tgz#aa572fcef11d6028097b6ef39c13fa9d62e5a441"
@@ -3141,7 +3294,7 @@
p-limit "3.1.0"
tslib "~2.3.0"
-"@graphql-tools/merge@^6.0.0", "@graphql-tools/merge@^6.2.12", "@graphql-tools/merge@^6.2.14":
+"@graphql-tools/merge@^6.0.0", "@graphql-tools/merge@^6.2.12":
version "6.2.14"
resolved "https://registry.npmjs.org/@graphql-tools/merge/-/merge-6.2.14.tgz#694e2a2785ba47558e5665687feddd2935e9d94e"
integrity sha512-RWT4Td0ROJai2eR66NHejgf8UwnXJqZxXgDWDI+7hua5vNA2OW8Mf9K1Wav1ZkjWnuRp4ztNtkZGie5ISw55ow==
@@ -3165,22 +3318,21 @@
dependencies:
tslib "~2.0.1"
-"@graphql-tools/prisma-loader@^6.3.0":
- version "6.3.0"
- resolved "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-6.3.0.tgz#c907e17751ff2b26e7c2bc75d0913ebf03f970da"
- integrity sha512-9V3W/kzsFBmUQqOsd96V4a4k7Didz66yh/IK89B1/rrvy9rYj+ULjEqR73x9BYZ+ww9FV8yP8LasWAJwWaqqJQ==
+"@graphql-tools/prisma-loader@^7.0.6":
+ version "7.1.1"
+ resolved "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-7.1.1.tgz#2a769919c97a3f7f7807668d3155c47999b0965c"
+ integrity sha512-9hVpG3BNsXAYMLPlZhSHubk6qBmiHLo/UlU0ldL100sMpqI46iBaHNhTNXZCSdd81hT+4HNqaDXNFqyKJ22OGQ==
dependencies:
- "@graphql-tools/url-loader" "^6.8.2"
- "@graphql-tools/utils" "^7.0.0"
- "@types/http-proxy-agent" "^2.0.2"
+ "@graphql-tools/url-loader" "^7.4.2"
+ "@graphql-tools/utils" "^8.5.1"
"@types/js-yaml" "^4.0.0"
"@types/json-stable-stringify" "^1.0.32"
"@types/jsonwebtoken" "^8.5.0"
chalk "^4.1.0"
debug "^4.3.1"
- dotenv "^8.2.0"
+ dotenv "^10.0.0"
graphql-request "^3.3.0"
- http-proxy-agent "^4.0.1"
+ http-proxy-agent "^5.0.0"
https-proxy-agent "^5.0.0"
isomorphic-fetch "^3.0.0"
js-yaml "^4.0.0"
@@ -3189,19 +3341,19 @@
lodash "^4.17.20"
replaceall "^0.1.6"
scuid "^1.1.0"
- tslib "~2.1.0"
+ tslib "~2.3.0"
yaml-ast-parser "^0.0.43"
-"@graphql-tools/relay-operation-optimizer@^6.3.0":
- version "6.3.0"
- resolved "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.3.0.tgz#f8c7f6c8aa4a9cf50ab151fbc5db4f4282a79532"
- integrity sha512-Or3UgRvkY9Fq1AAx7q38oPqFmTepLz7kp6wDHKyR0ceG7AvHv5En22R12mAeISInbhff4Rpwgf6cE8zHRu6bCw==
+"@graphql-tools/relay-operation-optimizer@^6.3.7":
+ version "6.4.1"
+ resolved "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.4.1.tgz#28572444e2c00850c889a84472f3cc7405dc1ad8"
+ integrity sha512-2b9D5L+31sIBnvmcmIW5tfvNUV+nJFtbHpUyarTRDmFT6EZ2cXo4WZMm9XJcHQD/Z5qvMXfPHxzQ3/JUs4xI+w==
dependencies:
- "@graphql-tools/utils" "^7.1.0"
- relay-compiler "10.1.0"
- tslib "~2.0.1"
+ "@graphql-tools/utils" "^8.5.1"
+ relay-compiler "12.0.0"
+ tslib "~2.3.0"
-"@graphql-tools/schema@8.3.1", "@graphql-tools/schema@^8.3.1":
+"@graphql-tools/schema@8.3.1", "@graphql-tools/schema@^8.1.2", "@graphql-tools/schema@^8.3.1":
version "8.3.1"
resolved "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz#1ee9da494d2da457643b3c93502b94c3c4b68c74"
integrity sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==
@@ -3220,7 +3372,7 @@
tslib "~2.2.0"
value-or-promise "1.0.6"
-"@graphql-tools/url-loader@^6.0.0", "@graphql-tools/url-loader@^6.10.1", "@graphql-tools/url-loader@^6.8.2":
+"@graphql-tools/url-loader@^6.0.0":
version "6.10.1"
resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-6.10.1.tgz#dc741e4299e0e7ddf435eba50a1f713b3e763b33"
integrity sha512-DSDrbhQIv7fheQ60pfDpGD256ixUQIR6Hhf9Z5bRjVkXOCvO5XrkwoWLiU7iHL81GB1r0Ba31bf+sl+D4nyyfw==
@@ -3245,6 +3397,31 @@
valid-url "1.0.9"
ws "7.4.5"
+"@graphql-tools/url-loader@^7.0.11":
+ version "7.7.0"
+ resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.7.0.tgz#504f0030c75b61bca4ac07da49e8cd872c316972"
+ integrity sha512-mBBb+aJqI4E0MVEzyfi76Pi/G6lGxGTVt/tP1YtKJly7UnonNoWOtDusdL3zIVAGhGgLsNrLbGhLDbwSd6TV6A==
+ dependencies:
+ "@graphql-tools/delegate" "^8.4.1"
+ "@graphql-tools/utils" "^8.5.1"
+ "@graphql-tools/wrap" "^8.3.1"
+ "@n1ru4l/graphql-live-query" "^0.9.0"
+ "@types/websocket" "^1.0.4"
+ "@types/ws" "^8.0.0"
+ cross-undici-fetch "^0.1.4"
+ dset "^3.1.0"
+ extract-files "^11.0.0"
+ graphql-sse "^1.0.1"
+ graphql-ws "^5.4.1"
+ isomorphic-ws "^4.0.1"
+ meros "^1.1.4"
+ subscriptions-transport-ws "^0.11.0"
+ sync-fetch "^0.3.1"
+ tslib "^2.3.0"
+ valid-url "^1.0.9"
+ value-or-promise "^1.0.11"
+ ws "^8.3.0"
+
"@graphql-tools/url-loader@^7.4.2":
version "7.5.3"
resolved "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-7.5.3.tgz#a594be40e3bc68d22f76746356e7f0b8117b7137"
@@ -3277,7 +3454,7 @@
dependencies:
tslib "~2.3.0"
-"@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.1.0", "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.5.0", "@graphql-tools/utils@^7.7.0", "@graphql-tools/utils@^7.7.1", "@graphql-tools/utils@^7.8.1", "@graphql-tools/utils@^7.9.0", "@graphql-tools/utils@^7.9.1":
+"@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.5.0", "@graphql-tools/utils@^7.7.0", "@graphql-tools/utils@^7.7.1", "@graphql-tools/utils@^7.8.1", "@graphql-tools/utils@^7.9.0":
version "7.10.0"
resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.10.0.tgz#07a4cb5d1bec1ff1dc1d47a935919ee6abd38699"
integrity sha512-d334r6bo9mxdSqZW6zWboEnnOOFRrAPVQJ7LkU8/6grglrbcu6WhwCLzHb90E94JI3TD3ricC3YGbUqIi9Xg0w==
@@ -3286,6 +3463,13 @@
camel-case "4.1.2"
tslib "~2.2.0"
+"@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.3.0", "@graphql-tools/utils@^8.5.2", "@graphql-tools/utils@^8.6.0":
+ version "8.6.0"
+ resolved "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.0.tgz#f424256a1f3b87d1dcf6f9f675739b2d3627be33"
+ integrity sha512-rnk+RHaOCeWnfekeQGRh5ycXK1ZAI7Nm0pbeLjA3SiysTdqhWyxNCp5ON4Mvtlid84OY/KB253fQq/2rotznCA==
+ dependencies:
+ tslib "~2.3.0"
+
"@graphql-tools/wrap@^7.0.4":
version "7.0.8"
resolved "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-7.0.8.tgz#ad41e487135ca3ea1ae0ea04bb3f596177fb4f50"
@@ -3349,19 +3533,19 @@
prop-types "^15.6.2"
scheduler "^0.19.0"
-"@humanwhocodes/config-array@^0.5.0":
- version "0.5.0"
- resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
- integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+"@humanwhocodes/config-array@^0.9.2":
+ version "0.9.2"
+ resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz#68be55c737023009dfc5fe245d51181bb6476914"
+ integrity sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==
dependencies:
- "@humanwhocodes/object-schema" "^1.2.0"
+ "@humanwhocodes/object-schema" "^1.2.1"
debug "^4.1.1"
minimatch "^3.0.4"
-"@humanwhocodes/object-schema@^1.2.0":
- version "1.2.0"
- resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf"
- integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==
+"@humanwhocodes/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
"@iarna/toml@^2.2.5":
version "2.2.5"
@@ -4561,9 +4745,9 @@
integrity sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==
"@microsoft/microsoft-graph-types@^2.6.0":
- version "2.8.0"
- resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.8.0.tgz#c3b538f99028e8609c5ebf95a494318a8f3d9201"
- integrity sha512-NDgLn9IhYD/+nCeeGAi1JM7xTFqaM6rkXfLfiC1xvXy48BGBUrAf8fNFq5fkzBvGY8HfjzdPIkrJkfvLL+rzDQ==
+ version "2.11.0"
+ resolved "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.11.0.tgz#0e1d3a0795855fc726e08836b1d3c4a72a8bcd00"
+ integrity sha512-v4Wuxp+kbcxeJGmb2UHbcukNr05XItFYXL+U3ReignI3Vl8tp1vfq0hkqP35Fun2QpqHJiu8Rkxj1MUF8d82ag==
"@microsoft/tsdoc-config@~0.15.2":
version "0.15.2"
@@ -4608,7 +4792,7 @@
outvariant "^1.2.0"
strict-event-emitter "^0.2.0"
-"@n1ru4l/graphql-live-query@0.9.0":
+"@n1ru4l/graphql-live-query@0.9.0", "@n1ru4l/graphql-live-query@^0.9.0":
version "0.9.0"
resolved "https://registry.npmjs.org/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz#defaebdd31f625bee49e6745934f36312532b2bc"
integrity sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg==
@@ -5025,19 +5209,19 @@
resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db"
integrity sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig==
-"@octokit/webhooks-types@4.15.0":
- version "4.15.0"
- resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-4.15.0.tgz#1158cba6578237d60957a37963a4a05654f5668b"
- integrity sha512-s9LgKsUzq/JH3PWDjaD/m1DIlC/QWgBWbmXVqjdxJXJQBA67KZrLWjStVlYPf0mWlVZ1MOKphDyHiOGCbs0+Kg==
+"@octokit/webhooks-types@5.2.0":
+ version "5.2.0"
+ resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-5.2.0.tgz#9d1d451f37460107409c81cab04dd473108abb02"
+ integrity sha512-OZhKy1w8/GF4GWtdiJc+o8sloWAHRueGB78FWFLZnueK7EHV9MzDVr4weJZMflJwMK4uuYLzcnJVnAoy3yB35g==
"@octokit/webhooks@^9.14.1":
- version "9.18.0"
- resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.18.0.tgz#19cc70e1ef281e33d830ea23e8011d25d8051f7f"
- integrity sha512-N2hP7vCouKk9UWZxvqgWTPbp34i6g9Om/jk+TZeZ5Z+VsKjXvGtONlEd9H8DM1yOeEC+ARDpfhraX6UsK5tesQ==
+ version "9.22.0"
+ resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.22.0.tgz#07a36a10358d39c1870758fae2b1ad3c24ca578d"
+ integrity sha512-wUd7nGfDRHG6xkz311djmq6lIB2tQ+r94SNkyv9o0bQhOsrkwH8fQCM7uVsbpkGUU2lqCYsVoa8z/UC9HJgRaw==
dependencies:
"@octokit/request-error" "^2.0.2"
"@octokit/webhooks-methods" "^2.0.0"
- "@octokit/webhooks-types" "4.15.0"
+ "@octokit/webhooks-types" "5.2.0"
aggregate-error "^3.1.0"
"@open-draft/until@^1.0.3":
@@ -6747,6 +6931,11 @@
resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+"@tootallnate/once@2":
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
+ integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
+
"@trendyol-js/openstack-swift-sdk@^0.0.5":
version "0.0.5"
resolved "https://registry.npmjs.org/@trendyol-js/openstack-swift-sdk/-/openstack-swift-sdk-0.0.5.tgz#65be3c42b8dbafc57f2f2a46c327e2ad51e5a70e"
@@ -7305,13 +7494,6 @@
resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.1.tgz#e81ad28a60bee0328c6d2384e029aec626f1ae67"
integrity sha512-e+2rjEwK6KDaNOm5Aa9wNGgyS9oSZU/4pfSMMPYNOfjvFI0WVXm29+ITRFr6aKDvvKo7uU1jV68MW4ScsfDi7Q==
-"@types/http-proxy-agent@^2.0.2":
- version "2.0.2"
- resolved "https://registry.npmjs.org/@types/http-proxy-agent/-/http-proxy-agent-2.0.2.tgz#942c1f35c7e1f0edd1b6ffae5d0f9051cfb32be1"
- integrity sha512-2S6IuBRhqUnH1/AUx9k8KWtY3Esg4eqri946MnxTG5HwehF1S5mqLln8fcyMiuQkY72p2gH3W+rIPqp5li0LyQ==
- dependencies:
- "@types/node" "*"
-
"@types/http-proxy-middleware@^0.19.3":
version "0.19.3"
resolved "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz#b2eb96fbc0f9ac7250b5d9c4c53aade049497d03"
@@ -7387,9 +7569,9 @@
"@types/istanbul-lib-report" "*"
"@types/jenkins@^0.23.1":
- version "0.23.2"
- resolved "https://registry.npmjs.org/@types/jenkins/-/jenkins-0.23.2.tgz#96736a2be4904efdfe7fe2650569479fd77dc48e"
- integrity sha512-BELmIZ6brxwGFqBHfLjLTjYRWAUqcT1d2BydH1CcRTZEjCYw3DRVfZkXU7BVlyIsKXm2ZMIKVkEjKKtVDvPiXA==
+ version "0.23.3"
+ resolved "https://registry.npmjs.org/@types/jenkins/-/jenkins-0.23.3.tgz#bca00a395147c8d448cfba6bb36241a56862f820"
+ integrity sha512-/uNktGT4d/NNIBZTur4cO4YU00fQ+iEe0Arm0l5v9Ixv6zwZR9u0V7XSuhWbWJkzKsh8aIeK66QxYqJvYF4yzA==
dependencies:
"@types/node" "*"
@@ -7842,9 +8024,9 @@
"@types/react" "*"
"@types/react-helmet@^6.1.0":
- version "6.1.1"
- resolved "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.1.tgz#4fde22cbcaa1b461642e1d719cc6162d95acb110"
- integrity sha512-VmSCMz6jp/06DABoY60vQa++h1YFt0PfAI23llxBJHbowqFgLUL0dhS1AQeVPNqYfRp9LAfokrfWACTNeobOrg==
+ version "6.1.5"
+ resolved "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.5.tgz#35f89a6b1646ee2bc342a33a9a6c8777933f9083"
+ integrity sha512-/ICuy7OHZxR0YCAZLNg9r7I9aijWUWvxaPR6uTuyxe8tAj5RL4Sw1+R6NhXUtOsarkGYPmaHdBDvuXh2DIN/uA==
dependencies:
"@types/react" "*"
@@ -8299,7 +8481,7 @@
dependencies:
"@types/node" "*"
-"@types/websocket@1.0.4":
+"@types/websocket@1.0.4", "@types/websocket@^1.0.4":
version "1.0.4"
resolved "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.4.tgz#1dc497280d8049a5450854dd698ee7e6ea9e60b8"
integrity sha512-qn1LkcFEKK8RPp459jkjzsfpbsx36BBt3oC3pITYtkoBw/aVX+EZFa5j3ThCRTNpLFvIMr5dSTD4RaMdilIOpA==
@@ -8382,109 +8564,85 @@
resolved "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71"
integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg==
-"@typescript-eslint/eslint-plugin@^v4.33.0":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276"
- integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==
+"@typescript-eslint/eslint-plugin@^5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz#382182d5cb062f52aac54434cfc47c28898c8006"
+ integrity sha512-qT4lr2jysDQBQOPsCCvpPUZHjbABoTJW8V9ZzIYKHMfppJtpdtzszDYsldwhFxlhvrp7aCHeXD1Lb9M1zhwWwQ==
dependencies:
- "@typescript-eslint/experimental-utils" "4.33.0"
- "@typescript-eslint/scope-manager" "4.33.0"
- debug "^4.3.1"
+ "@typescript-eslint/experimental-utils" "5.9.0"
+ "@typescript-eslint/scope-manager" "5.9.0"
+ "@typescript-eslint/type-utils" "5.9.0"
+ debug "^4.3.2"
functional-red-black-tree "^1.0.1"
ignore "^5.1.8"
- regexpp "^3.1.0"
+ regexpp "^3.2.0"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/experimental-utils@4.33.0", "@typescript-eslint/experimental-utils@^4.0.1":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd"
- integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==
+"@typescript-eslint/experimental-utils@5.9.0", "@typescript-eslint/experimental-utils@^5.0.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.9.0.tgz#652762d37d6565ef07af285021b8347b6c79a827"
+ integrity sha512-ZnLVjBrf26dn7ElyaSKa6uDhqwvAi4jBBmHK1VxuFGPRAxhdi18ubQYSGA7SRiFiES3q9JiBOBHEBStOFkwD2g==
dependencies:
- "@types/json-schema" "^7.0.7"
- "@typescript-eslint/scope-manager" "4.33.0"
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/typescript-estree" "4.33.0"
+ "@types/json-schema" "^7.0.9"
+ "@typescript-eslint/scope-manager" "5.9.0"
+ "@typescript-eslint/types" "5.9.0"
+ "@typescript-eslint/typescript-estree" "5.9.0"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
-"@typescript-eslint/parser@^v4.28.3":
- version "4.28.3"
- resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.3.tgz#95f1d475c08268edffdcb2779993c488b6434b44"
- integrity sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ==
+"@typescript-eslint/parser@^5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.9.0.tgz#fdbb08767a4caa6ca6ccfed5f9ffe9387f0c7d97"
+ integrity sha512-/6pOPz8yAxEt4PLzgbFRDpZmHnXCeZgPDrh/1DaVKOjvn/UPMlWhbx/gA96xRi2JxY1kBl2AmwVbyROUqys5xQ==
dependencies:
- "@typescript-eslint/scope-manager" "4.28.3"
- "@typescript-eslint/types" "4.28.3"
- "@typescript-eslint/typescript-estree" "4.28.3"
- debug "^4.3.1"
+ "@typescript-eslint/scope-manager" "5.9.0"
+ "@typescript-eslint/types" "5.9.0"
+ "@typescript-eslint/typescript-estree" "5.9.0"
+ debug "^4.3.2"
-"@typescript-eslint/scope-manager@4.28.3":
- version "4.28.3"
- resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz#c32ad4491b3726db1ba34030b59ea922c214e371"
- integrity sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ==
+"@typescript-eslint/scope-manager@5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.9.0.tgz#02dfef920290c1dcd7b1999455a3eaae7a1a3117"
+ integrity sha512-DKtdIL49Qxk2a8icF6whRk7uThuVz4A6TCXfjdJSwOsf+9ree7vgQWcx0KOyCdk0i9ETX666p4aMhrRhxhUkyg==
dependencies:
- "@typescript-eslint/types" "4.28.3"
- "@typescript-eslint/visitor-keys" "4.28.3"
+ "@typescript-eslint/types" "5.9.0"
+ "@typescript-eslint/visitor-keys" "5.9.0"
-"@typescript-eslint/scope-manager@4.33.0":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3"
- integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==
+"@typescript-eslint/type-utils@5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.9.0.tgz#fd5963ead04bc9b7af9c3a8e534d8d39f1ce5f93"
+ integrity sha512-uVCb9dJXpBrK1071ri5aEW7ZHdDHAiqEjYznF3HSSvAJXyrkxGOw2Ejibz/q6BXdT8lea8CMI0CzKNFTNI6TEQ==
dependencies:
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/visitor-keys" "4.33.0"
+ "@typescript-eslint/experimental-utils" "5.9.0"
+ debug "^4.3.2"
+ tsutils "^3.21.0"
-"@typescript-eslint/types@4.28.3":
- version "4.28.3"
- resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.3.tgz#8fffd436a3bada422c2c1da56060a0566a9506c7"
- integrity sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA==
+"@typescript-eslint/types@5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.9.0.tgz#e5619803e39d24a03b3369506df196355736e1a3"
+ integrity sha512-mWp6/b56Umo1rwyGCk8fPIzb9Migo8YOniBGPAQDNC6C52SeyNGN4gsVwQTAR+RS2L5xyajON4hOLwAGwPtUwg==
-"@typescript-eslint/types@4.33.0":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
- integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
-
-"@typescript-eslint/typescript-estree@4.28.3":
- version "4.28.3"
- resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz#253d7088100b2a38aefe3c8dd7bd1f8232ec46fb"
- integrity sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w==
+"@typescript-eslint/typescript-estree@5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.0.tgz#0e5c6f03f982931abbfbc3c1b9df5fbf92a3490f"
+ integrity sha512-kxo3xL2mB7XmiVZcECbaDwYCt3qFXz99tBSuVJR4L/sR7CJ+UNAPrYILILktGj1ppfZ/jNt/cWYbziJUlHl1Pw==
dependencies:
- "@typescript-eslint/types" "4.28.3"
- "@typescript-eslint/visitor-keys" "4.28.3"
- debug "^4.3.1"
- globby "^11.0.3"
- is-glob "^4.0.1"
+ "@typescript-eslint/types" "5.9.0"
+ "@typescript-eslint/visitor-keys" "5.9.0"
+ debug "^4.3.2"
+ globby "^11.0.4"
+ is-glob "^4.0.3"
semver "^7.3.5"
tsutils "^3.21.0"
-"@typescript-eslint/typescript-estree@4.33.0":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609"
- integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==
+"@typescript-eslint/visitor-keys@5.9.0":
+ version "5.9.0"
+ resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.0.tgz#7585677732365e9d27f1878150fab3922784a1a6"
+ integrity sha512-6zq0mb7LV0ThExKlecvpfepiB+XEtFv/bzx7/jKSgyXTFD7qjmSu1FoiS0x3OZaiS+UIXpH2vd9O89f02RCtgw==
dependencies:
- "@typescript-eslint/types" "4.33.0"
- "@typescript-eslint/visitor-keys" "4.33.0"
- debug "^4.3.1"
- globby "^11.0.3"
- is-glob "^4.0.1"
- semver "^7.3.5"
- tsutils "^3.21.0"
-
-"@typescript-eslint/visitor-keys@4.28.3":
- version "4.28.3"
- resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz#26ac91e84b23529968361045829da80a4e5251c4"
- integrity sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg==
- dependencies:
- "@typescript-eslint/types" "4.28.3"
- eslint-visitor-keys "^2.0.0"
-
-"@typescript-eslint/visitor-keys@4.33.0":
- version "4.33.0"
- resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
- integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==
- dependencies:
- "@typescript-eslint/types" "4.33.0"
- eslint-visitor-keys "^2.0.0"
+ "@typescript-eslint/types" "5.9.0"
+ eslint-visitor-keys "^3.0.0"
"@webassemblyjs/ast@1.11.1":
version "1.11.1"
@@ -8865,7 +9023,7 @@ acorn@^6.4.1:
resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474"
integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==
-acorn@^7.1.1, acorn@^7.4.0:
+acorn@^7.1.1:
version "7.4.1"
resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
@@ -8880,6 +9038,11 @@ acorn@^8.4.1:
resolved "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c"
integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==
+acorn@^8.7.0:
+ version "8.7.0"
+ resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
+ integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
+
add-stream@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
@@ -8982,16 +9145,6 @@ ajv@^7.0.3:
require-from-string "^2.0.2"
uri-js "^4.2.2"
-ajv@^8.0.1:
- version "8.6.0"
- resolved "https://registry.npmjs.org/ajv/-/ajv-8.6.0.tgz#60cc45d9c46a477d80d92c48076d972c342e5720"
- integrity sha512-cnUG4NSBiM4YFBxgZIj/In3/6KX+rQ2l2YPRVcvAMQGWEPKuXoPIhxzwqh31jA3IPbI4qEOp/5ILI4ynioXsGQ==
- dependencies:
- fast-deep-equal "^3.1.1"
- json-schema-traverse "^1.0.0"
- require-from-string "^2.0.2"
- uri-js "^4.2.2"
-
alphanum-sort@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
@@ -9471,7 +9624,7 @@ array-ify@^1.0.0:
resolved "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
-array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.2, array-includes@^3.1.4:
+array-includes@^3.0.3, array-includes@^3.1.2, array-includes@^3.1.3, array-includes@^3.1.4:
version "3.1.4"
resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9"
integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==
@@ -9513,7 +9666,7 @@ array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.5:
define-properties "^1.1.3"
es-abstract "^1.19.0"
-array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.4, array.prototype.flatmap@^1.2.5:
+array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.2.5:
version "1.2.5"
resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446"
integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==
@@ -9753,11 +9906,16 @@ aws4@^1.11.0, aws4@^1.8.0:
resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
-axe-core@^4.0.2, axe-core@^4.2.0:
+axe-core@^4.2.0:
version "4.3.1"
resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.3.1.tgz#0c6a076e4a1c3e0544ba6a9479158f9be7a7928e"
integrity sha512-3WVgVPs/7OnKU3s+lqMtkv3wQlg3WxK1YifmpJSDO0E1aPBrZWlrrTO6cxRqCXLuX2aYgCljqXIQd0VnRidV0g==
+axe-core@^4.3.5:
+ version "4.3.5"
+ resolved "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5"
+ integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==
+
axios-cached-dns-resolve@0.5.2:
version "0.5.2"
resolved "https://registry.npmjs.org/axios-cached-dns-resolve/-/axios-cached-dns-resolve-0.5.2.tgz#38cd89fd491fa7a48d04fb421291085c640fe79e"
@@ -9992,10 +10150,10 @@ babel-preset-current-node-syntax@^1.0.0:
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-syntax-top-level-await" "^7.8.3"
-babel-preset-fbjs@^3.3.0:
- version "3.3.0"
- resolved "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.3.0.tgz#a6024764ea86c8e06a22d794ca8b69534d263541"
- integrity sha512-7QTLTCd2gwB2qGoi5epSULMHugSVgpcVt5YAeiFO9ABLrutDQzKfGwzxgZHLpugq8qMdg/DhRZDZ5CLKxBkEbw==
+babel-preset-fbjs@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c"
+ integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==
dependencies:
"@babel/plugin-proposal-class-properties" "^7.0.0"
"@babel/plugin-proposal-object-rest-spread" "^7.0.0"
@@ -10447,13 +10605,13 @@ browserslist@4.14.2:
escalade "^3.0.2"
node-releases "^1.1.61"
-browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.5, browserslist@^4.16.6:
- version "4.18.1"
- resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f"
- integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==
+browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1:
+ version "4.19.1"
+ resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3"
+ integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==
dependencies:
- caniuse-lite "^1.0.30001280"
- electron-to-chromium "^1.3.896"
+ caniuse-lite "^1.0.30001286"
+ electron-to-chromium "^1.4.17"
escalade "^3.1.1"
node-releases "^2.0.1"
picocolors "^1.0.0"
@@ -10500,11 +10658,6 @@ buffer-indexof@^1.0.0:
resolved "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c"
integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==
-buffer-writer@1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08"
- integrity sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=
-
buffer-writer@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
@@ -10817,11 +10970,16 @@ caniuse-api@^3.0.0:
lodash.memoize "^4.1.2"
lodash.uniq "^4.5.0"
-caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001280:
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001125:
version "1.0.30001282"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001282.tgz#38c781ee0a90ccfe1fe7fefd00e43f5ffdcb96fd"
integrity sha512-YhF/hG6nqBEllymSIjLtR2iWDDnChvhnVJqp+vloyt2tEHFG1yBR+ac2B/rOw0qOK0m0lEXU2dv4E/sMk5P9Kg==
+caniuse-lite@^1.0.30001286:
+ version "1.0.30001296"
+ resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz#d99f0f3bee66544800b93d261c4be55a35f1cec8"
+ integrity sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q==
+
canvas@^2.6.1:
version "2.8.0"
resolved "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz#f99ca7f25e6e26686661ffa4fec1239bbef74461"
@@ -10883,7 +11041,7 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
-chalk@4.1.1, chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
+chalk@4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
@@ -10910,6 +11068,14 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
change-case-all@1.0.14:
version "1.0.14"
resolved "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1"
@@ -11426,7 +11592,7 @@ colors@1.0.3:
resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
-colors@^1.1.2, colors@^1.2.1:
+colors@1.4.0, colors@^1.1.2, colors@^1.2.1:
version "1.4.0"
resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
@@ -11514,7 +11680,12 @@ common-ancestor-path@^1.0.1:
resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7"
integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==
-common-tags@1.8.0, common-tags@^1.8.0:
+common-tags@1.8.2:
+ version "1.8.2"
+ resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+ integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
+
+common-tags@^1.8.0:
version "1.8.0"
resolved "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==
@@ -11623,15 +11794,14 @@ concat-with-sourcemaps@^1.1.0:
dependencies:
source-map "^0.6.1"
-concurrently@^6.0.0:
- version "6.2.0"
- resolved "https://registry.npmjs.org/concurrently/-/concurrently-6.2.0.tgz#587e2cb8afca7234172d8ea55176088632c4c56d"
- integrity sha512-v9I4Y3wFoXCSY2L73yYgwA9ESrQMpRn80jMcqMgHx720Hecz2GZAvTI6bREVST6lkddNypDKRN22qhK0X8Y00g==
+concurrently@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/concurrently/-/concurrently-7.0.0.tgz#78d31b441cec338dab03316c221a2f9a67c529b0"
+ integrity sha512-WKM7PUsI8wyXpF80H+zjHP32fsgsHNQfPLw/e70Z5dYkV7hF+rf8q3D+ScWJIEr57CpkO3OWBko6hwhQLPR8Pw==
dependencies:
chalk "^4.1.0"
date-fns "^2.16.1"
lodash "^4.17.21"
- read-pkg "^5.2.0"
rxjs "^6.6.3"
spawn-command "^0.0.2-1"
supports-color "^8.1.0"
@@ -12036,13 +12206,6 @@ cross-env@^7.0.0:
dependencies:
cross-spawn "^7.0.1"
-cross-fetch@3.0.6:
- version "3.0.6"
- resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz#3a4040bc8941e653e0e9cf17f29ebcd177d3365c"
- integrity sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==
- dependencies:
- node-fetch "2.6.1"
-
cross-fetch@3.1.4, cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.3, cross-fetch@^3.1.4:
version "3.1.4"
resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
@@ -12079,6 +12242,16 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
+cross-undici-fetch@^0.0.20:
+ version "0.0.20"
+ resolved "https://registry.npmjs.org/cross-undici-fetch/-/cross-undici-fetch-0.0.20.tgz#6b7c5ac82a3601edd439f37275ac0319d77a120a"
+ integrity sha512-5d3WBC4VRHpFndECK9bx4TngXrw0OUXdhX561Ty1ZoqMASz9uf55BblhTC1CO6GhMWnvk9SOqYEXQliq6D2P4A==
+ dependencies:
+ abort-controller "^3.0.0"
+ form-data "^4.0.0"
+ node-fetch "^2.6.5"
+ undici "^4.9.3"
+
cross-undici-fetch@^0.0.26:
version "0.0.26"
resolved "https://registry.npmjs.org/cross-undici-fetch/-/cross-undici-fetch-0.0.26.tgz#29d93d56609f4d2334f9d5333d23ef7a242842a7"
@@ -12089,6 +12262,17 @@ cross-undici-fetch@^0.0.26:
node-fetch "^2.6.5"
undici "^4.9.3"
+cross-undici-fetch@^0.1.4:
+ version "0.1.13"
+ resolved "https://registry.npmjs.org/cross-undici-fetch/-/cross-undici-fetch-0.1.13.tgz#807d17ce5c524c21bc0a6486e97ecccb901c6529"
+ integrity sha512-nF+g932BrKPoK0RZQKRA9S2IKXeveGPJlaUWXyUEGjjSpAdxBhEHDrMDbiksP2iSNe8O5vn1bN3tTvrd6+yFSg==
+ dependencies:
+ abort-controller "^3.0.0"
+ form-data-encoder "^1.7.1"
+ formdata-node "^4.3.1"
+ node-fetch "^2.6.5"
+ undici "^4.9.3"
+
crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
@@ -12627,10 +12811,10 @@ dagre@^0.8.5:
graphlib "^2.1.8"
lodash "^4.17.15"
-damerau-levenshtein@^1.0.6:
- version "1.0.6"
- resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791"
- integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==
+damerau-levenshtein@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz#64368003512a1a6992593741a09a9d31a836f55d"
+ integrity sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==
dargs@^7.0.0:
version "7.0.0"
@@ -12700,7 +12884,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9:
dependencies:
ms "2.0.0"
-debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
+debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2:
version "4.3.2"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
@@ -13280,12 +13464,17 @@ dotenv-webpack@^1.8.0:
dependencies:
dotenv-defaults "^1.0.2"
+dotenv@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
+ integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
+
dotenv@^6.2.0:
version "6.2.0"
resolved "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
-dotenv@^8.0.0, dotenv@^8.2.0:
+dotenv@^8.0.0:
version "8.2.0"
resolved "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
@@ -13329,6 +13518,11 @@ duplexer@^0.1.1, duplexer@~0.1.1:
resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
+duplexer@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+ integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+
duplexify@^3.4.2, duplexify@^3.6.0:
version "3.7.1"
resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
@@ -13391,11 +13585,16 @@ elastic-builder@^2.16.0:
lodash.isstring "^4.0.1"
lodash.omit "^4.5.0"
-electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.896:
+electron-to-chromium@^1.3.564:
version "1.3.900"
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.900.tgz#5be2c5818a2a012c511b4b43e87b6ab7a296d4f5"
integrity sha512-SuXbQD8D4EjsaBaJJxySHbC+zq8JrFfxtb4GIr4E9n1BcROyMcRrJCYQNpJ9N+Wjf5mFp7Wp0OHykd14JNEzzQ==
+electron-to-chromium@^1.4.17:
+ version "1.4.35"
+ resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.35.tgz#69aabb73d7030733e71c1e970ec16f5ceefbaea4"
+ integrity sha512-wzTOMh6HGFWeALMI3bif0mzgRrVGyP1BdFRx7IvWukFrSC5QVQELENuy+Fm2dCrAdQH9T3nuqr07n94nPDFBWA==
+
elegant-spinner@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e"
@@ -13436,7 +13635,7 @@ emoji-regex@^8.0.0:
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
-emoji-regex@^9.0.0:
+emoji-regex@^9.2.2:
version "9.2.2"
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
@@ -13759,6 +13958,18 @@ esbuild-linux-s390x@0.14.10:
resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.10.tgz#cc4228ac842febc48b84757814bed964a619be62"
integrity sha512-knArKKZm0ypIYWOWyOT7+accVwbVV1LZnl2FWWy05u9Tyv5oqJ2F5+X2Vqe/gqd61enJXQWqoufXopvG3zULOg==
+esbuild-loader@^2.18.0:
+ version "2.18.0"
+ resolved "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-2.18.0.tgz#7b9548578ab954574fd94655693d22aa5ec74120"
+ integrity sha512-AKqxM3bI+gvGPV8o6NAhR+cBxVO8+dh+O0OXBHIXXwuSGumckbPWHzZ17subjBGI2YEGyJ1STH7Haj8aCrwL/w==
+ dependencies:
+ esbuild "^0.14.6"
+ joycon "^3.0.1"
+ json5 "^2.2.0"
+ loader-utils "^2.0.0"
+ tapable "^2.2.0"
+ webpack-sources "^2.2.0"
+
esbuild-netbsd-64@0.14.10:
version "0.14.10"
resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.10.tgz#6ec50d9e4547a7579f447307b19f66bbedfd868b"
@@ -13789,7 +14000,7 @@ esbuild-windows-arm64@0.14.10:
resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.10.tgz#50ab9a83f6ccf71c272e58489ecc4d7375075f32"
integrity sha512-OJOyxDtabvcUYTc+O4dR0JMzLBz6G9+gXIHA7Oc5d5Fv1xiYa0nUeo8+W5s2e6ZkPRdIwOseYoL70rZz80S5BA==
-esbuild@^0.14.1:
+esbuild@^0.14.1, esbuild@^0.14.10, esbuild@^0.14.6:
version "0.14.10"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.10.tgz#10268d2b576b25ed6f8554553413988628a7767b"
integrity sha512-ibZb+NwFqBwHHJlpnFMtg4aNmVK+LUtYMFC9CuKs6lDCBEvCHpqCFZFEirpqt1jOugwKGx8gALNGvX56lQyfew==
@@ -13896,7 +14107,7 @@ eslint-import-resolver-node@^0.3.6:
debug "^3.2.7"
resolve "^1.20.0"
-eslint-module-utils@^2.1.1, eslint-module-utils@^2.7.1:
+eslint-module-utils@^2.1.1:
version "2.7.1"
resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.1.tgz#b435001c9f8dd4ab7f6d0efcae4b9696d4c24b7c"
integrity sha512-fjoetBXQZq2tSTWZ9yWVl2KuFrTZZH3V+9iD1V1RfpDgxzJR+mPd/KZmMiA8gbPqdBzpNiEHOuT7IYEWxrH0zQ==
@@ -13905,6 +14116,14 @@ eslint-module-utils@^2.1.1, eslint-module-utils@^2.7.1:
find-up "^2.1.0"
pkg-dir "^2.0.0"
+eslint-module-utils@^2.7.2:
+ version "2.7.2"
+ resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz#1d0aa455dcf41052339b63cada8ab5fd57577129"
+ integrity sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==
+ dependencies:
+ debug "^3.2.7"
+ find-up "^2.1.0"
+
eslint-plugin-cypress@^2.10.3:
version "2.12.1"
resolved "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz#9aeee700708ca8c058e00cdafe215199918c2632"
@@ -13922,48 +14141,49 @@ eslint-plugin-graphql@^4.0.0:
lodash.flatten "^4.4.0"
lodash.without "^4.4.0"
-eslint-plugin-import@^2.20.2:
- version "2.25.3"
- resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766"
- integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==
+eslint-plugin-import@^2.25.4:
+ version "2.25.4"
+ resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
+ integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
dependencies:
array-includes "^3.1.4"
array.prototype.flat "^1.2.5"
debug "^2.6.9"
doctrine "^2.1.0"
eslint-import-resolver-node "^0.3.6"
- eslint-module-utils "^2.7.1"
+ eslint-module-utils "^2.7.2"
has "^1.0.3"
is-core-module "^2.8.0"
is-glob "^4.0.3"
minimatch "^3.0.4"
object.values "^1.1.5"
resolve "^1.20.0"
- tsconfig-paths "^3.11.0"
+ tsconfig-paths "^3.12.0"
-eslint-plugin-jest@^24.1.0:
- version "24.3.6"
- resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.3.6.tgz#5f0ca019183c3188c5ad3af8e80b41de6c8e9173"
- integrity sha512-WOVH4TIaBLIeCX576rLcOgjNXqP+jNlCiEmRgFTfQtJ52DpwnIQKAVGlGPAN7CZ33bW6eNfHD6s8ZbEUTQubJg==
+eslint-plugin-jest@^25.3.4:
+ version "25.3.4"
+ resolved "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.3.4.tgz#2031dfe495be1463330f8b80096ddc91f8e6387f"
+ integrity sha512-CCnwG71wvabmwq/qkz0HWIqBHQxw6pXB1uqt24dxqJ9WB34pVg49bL1sjXphlJHgTMWGhBjN1PicdyxDxrfP5A==
dependencies:
- "@typescript-eslint/experimental-utils" "^4.0.1"
+ "@typescript-eslint/experimental-utils" "^5.0.0"
-eslint-plugin-jsx-a11y@^6.2.1:
- version "6.4.1"
- resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd"
- integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==
+eslint-plugin-jsx-a11y@^6.5.1:
+ version "6.5.1"
+ resolved "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
+ integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==
dependencies:
- "@babel/runtime" "^7.11.2"
+ "@babel/runtime" "^7.16.3"
aria-query "^4.2.2"
- array-includes "^3.1.1"
+ array-includes "^3.1.4"
ast-types-flow "^0.0.7"
- axe-core "^4.0.2"
+ axe-core "^4.3.5"
axobject-query "^2.2.0"
- damerau-levenshtein "^1.0.6"
- emoji-regex "^9.0.0"
+ damerau-levenshtein "^1.0.7"
+ emoji-regex "^9.2.2"
has "^1.0.3"
- jsx-ast-utils "^3.1.0"
+ jsx-ast-utils "^3.2.1"
language-tags "^1.0.5"
+ minimatch "^3.0.4"
eslint-plugin-monorepo@^0.3.2:
version "0.3.2"
@@ -13987,15 +14207,15 @@ eslint-plugin-notice@^0.9.10:
lodash "^4.17.15"
metric-lcs "^0.1.2"
-eslint-plugin-react-hooks@^4.0.0:
- version "4.2.0"
- resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556"
- integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==
+eslint-plugin-react-hooks@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
+ integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
-eslint-plugin-react@^7.12.4:
- version "7.27.1"
- resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz#469202442506616f77a854d91babaae1ec174b45"
- integrity sha512-meyunDjMMYeWr/4EBLTV1op3iSG3mjT/pz5gti38UzfM4OPpNc2m0t2xvKCOMU5D6FSdd34BIMFOvQbW+i8GAA==
+eslint-plugin-react@^7.28.0:
+ version "7.28.0"
+ resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz#8f3ff450677571a659ce76efc6d80b6a525adbdf"
+ integrity sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==
dependencies:
array-includes "^3.1.4"
array.prototype.flatmap "^1.2.5"
@@ -14028,12 +14248,13 @@ eslint-scope@^4.0.3:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-utils@^2.1.0:
- version "2.1.0"
- resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
- integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
+eslint-scope@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153"
+ integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==
dependencies:
- eslint-visitor-keys "^1.1.0"
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
eslint-utils@^3.0.0:
version "3.0.0"
@@ -14042,47 +14263,46 @@ eslint-utils@^3.0.0:
dependencies:
eslint-visitor-keys "^2.0.0"
-eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
- version "1.3.0"
- resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
- integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
-
eslint-visitor-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@^7.30.0:
- version "7.30.0"
- resolved "https://registry.npmjs.org/eslint/-/eslint-7.30.0.tgz#6d34ab51aaa56112fd97166226c9a97f505474f8"
- integrity sha512-VLqz80i3as3NdloY44BQSJpFw534L9Oh+6zJOUaViV4JPd+DaHwutqP7tcpkW3YiXbK6s05RZl7yl7cQn+lijg==
+eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2"
+ integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==
+
+eslint@^8.6.0:
+ version "8.6.0"
+ resolved "https://registry.npmjs.org/eslint/-/eslint-8.6.0.tgz#4318c6a31c5584838c1a2e940c478190f58d558e"
+ integrity sha512-UvxdOJ7mXFlw7iuHZA4jmzPaUqIw54mZrv+XPYKNbKdLR0et4rf60lIZUU9kiNtnzzMzGWxMV+tQ7uG7JG8DPw==
dependencies:
- "@babel/code-frame" "7.12.11"
- "@eslint/eslintrc" "^0.4.2"
- "@humanwhocodes/config-array" "^0.5.0"
+ "@eslint/eslintrc" "^1.0.5"
+ "@humanwhocodes/config-array" "^0.9.2"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
- debug "^4.0.1"
+ debug "^4.3.2"
doctrine "^3.0.0"
enquirer "^2.3.5"
escape-string-regexp "^4.0.0"
- eslint-scope "^5.1.1"
- eslint-utils "^2.1.0"
- eslint-visitor-keys "^2.0.0"
- espree "^7.3.1"
+ eslint-scope "^7.1.0"
+ eslint-utils "^3.0.0"
+ eslint-visitor-keys "^3.1.0"
+ espree "^9.3.0"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
- glob-parent "^5.1.2"
+ glob-parent "^6.0.1"
globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
- js-yaml "^3.13.1"
+ js-yaml "^4.1.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash.merge "^4.6.2"
@@ -14090,11 +14310,10 @@ eslint@^7.30.0:
natural-compare "^1.4.0"
optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^3.1.0"
+ regexpp "^3.2.0"
semver "^7.2.1"
- strip-ansi "^6.0.0"
+ strip-ansi "^6.0.1"
strip-json-comments "^3.1.0"
- table "^6.0.9"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -14103,14 +14322,14 @@ esm@^3.2.25:
resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
-espree@^7.3.0, espree@^7.3.1:
- version "7.3.1"
- resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
- integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
+espree@^9.2.0, espree@^9.3.0:
+ version "9.3.0"
+ resolved "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8"
+ integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==
dependencies:
- acorn "^7.4.0"
+ acorn "^8.7.0"
acorn-jsx "^5.3.1"
- eslint-visitor-keys "^1.3.0"
+ eslint-visitor-keys "^3.1.0"
esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0:
version "4.0.1"
@@ -14504,7 +14723,7 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-extract-files@11.0.0:
+extract-files@11.0.0, extract-files@^11.0.0:
version "11.0.0"
resolved "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a"
integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==
@@ -14771,10 +14990,10 @@ filesize@6.1.0:
resolved "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00"
integrity sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==
-filesize@^6.1.0:
- version "6.4.0"
- resolved "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz#914f50471dd66fdca3cefe628bd0cde4ef769bcd"
- integrity sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==
+filesize@^8.0.6:
+ version "8.0.6"
+ resolved "https://registry.npmjs.org/filesize/-/filesize-8.0.6.tgz#5f0c27aa1b507fa7d9f72c912a774ca6a44111b1"
+ integrity sha512-sHvRqTiwdmcuzqet7iVwsbwF6UrV3wIgDf2SHNdY1Hgl8PC45HZg/0xtdw6U2izIV4lccnrY9ftl6wZFNdjYMg==
fill-range@^4.0.0:
version "4.0.0"
@@ -14986,29 +15205,10 @@ fork-ts-checker-webpack-plugin@4.1.6, fork-ts-checker-webpack-plugin@^4.0.5, for
tapable "^1.0.0"
worker-rpc "^0.1.0"
-fork-ts-checker-webpack-plugin@^6.0.4:
- version "6.3.1"
- resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.3.1.tgz#938535f844cdddf6796211e5761da27341b9fcd3"
- integrity sha512-uxqlKTEeSJ5/JRr0zaCiw2U+kOV8F4/MhCnnRf6vbxj4ZU3Or0DLl/0CNtXro7uLWDssnuR7wUN7fU9w1I0REA==
- dependencies:
- "@babel/code-frame" "^7.8.3"
- "@types/json-schema" "^7.0.5"
- chalk "^4.1.0"
- chokidar "^3.4.2"
- cosmiconfig "^6.0.0"
- deepmerge "^4.2.2"
- fs-extra "^9.0.0"
- glob "^7.1.6"
- memfs "^3.1.2"
- minimatch "^3.0.4"
- schema-utils "2.7.0"
- semver "^7.3.2"
- tapable "^1.0.0"
-
-fork-ts-checker-webpack-plugin@^6.0.5:
- version "6.4.2"
- resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.4.2.tgz#6d307fb4072ce4abe4d56a89c8ef060066f33d81"
- integrity sha512-EqtzzRdx2mldr0KEydSN9jaNrf419gMpwkloumG6K/S7jtJc9Fl7wMJ+y+o7DLLGMMU/kouYr06agTD/YkxzIQ==
+fork-ts-checker-webpack-plugin@^6.0.4, fork-ts-checker-webpack-plugin@^6.5.0:
+ version "6.5.0"
+ resolved "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e"
+ integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==
dependencies:
"@babel/code-frame" "^7.8.3"
"@types/json-schema" "^7.0.5"
@@ -15029,6 +15229,11 @@ form-data-encoder@^1.4.3:
resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.6.0.tgz#9dd1f479836c1b1b47201667c68f8daafa800943"
integrity sha512-P97AVaOB8hZaniiKK3f46zxQcchQXI8EgBnX+2+719gLv5ZbDSf3J1XtIuAQ8xbGLU4vZYhy7xwhFtK8U5u9Nw==
+form-data-encoder@^1.7.1:
+ version "1.7.1"
+ resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96"
+ integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==
+
form-data@4.0.0, form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
@@ -15078,6 +15283,14 @@ formdata-node@^4.0.0:
node-domexception "1.0.0"
web-streams-polyfill "4.0.0-beta.1"
+formdata-node@^4.3.1:
+ version "4.3.2"
+ resolved "https://registry.npmjs.org/formdata-node/-/formdata-node-4.3.2.tgz#0262e94931e36db7239c2b08bdb6aaf18ec47d21"
+ integrity sha512-k7lYJyzDOSL6h917favP8j1L0/wNyylzU+x+1w4p5haGVHNlP58dbpdJhiCUsDbWsa9HwEtLp89obQgXl2e0qg==
+ dependencies:
+ node-domexception "1.0.0"
+ web-streams-polyfill "4.0.0-beta.1"
+
formidable@^1.2.2:
version "1.2.2"
resolved "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9"
@@ -15317,11 +15530,6 @@ generic-names@^2.0.1:
dependencies:
loader-utils "^1.1.0"
-generic-pool@2.4.3:
- version "2.4.3"
- resolved "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff"
- integrity sha1-eAw29p360FpaBF3Te+etyhGk9v8=
-
gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@@ -15513,13 +15721,20 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2:
+glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
+glob-parent@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
glob-promise@^3.4.0:
version "3.4.0"
resolved "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz#b6b8f084504216f702dc2ce8c9bc9ac8866fdb20"
@@ -15653,7 +15868,7 @@ globby@11.0.3:
merge2 "^1.3.0"
slash "^3.0.0"
-globby@^11.0.0, globby@^11.0.1, globby@^11.0.2, globby@^11.0.3:
+globby@^11.0.0, globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4:
version "11.0.4"
resolved "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==
@@ -15798,7 +16013,7 @@ graphlib@^2.1.8:
dependencies:
lodash "^4.17.15"
-graphql-config@^3.0.2, graphql-config@^3.3.0:
+graphql-config@^3.0.2:
version "3.3.0"
resolved "https://registry.npmjs.org/graphql-config/-/graphql-config-3.3.0.tgz#24c3672a427cb67c0c717ca3b9d70e9f0c9e752b"
integrity sha512-mSQIsPMssr7QrgqhnjI+CyVH6oQgCrgS6irHsTvwf7RFDRnR2k9kqpQOQgVoOytBSn0DOYryS0w0SAg9xor/Jw==
@@ -15990,7 +16205,7 @@ gud@^1.0.0:
resolved "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0"
integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==
-gzip-size@5.1.1, gzip-size@^5.1.1:
+gzip-size@5.1.1:
version "5.1.1"
resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==
@@ -15998,6 +16213,13 @@ gzip-size@5.1.1, gzip-size@^5.1.1:
duplexer "^0.1.1"
pify "^4.0.1"
+gzip-size@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
+ integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
+ dependencies:
+ duplexer "^0.1.2"
+
handle-thing@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754"
@@ -16210,6 +16432,11 @@ hast-util-to-parse5@^6.0.0:
xtend "^4.0.0"
zwitch "^1.0.0"
+hast-util-whitespace@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c"
+ integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==
+
hastscript@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640"
@@ -16471,6 +16698,15 @@ http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1:
agent-base "6"
debug "4"
+http-proxy-agent@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43"
+ integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==
+ dependencies:
+ "@tootallnate/once" "2"
+ agent-base "6"
+ debug "4"
+
http-proxy-middleware@^1.0.0:
version "1.3.1"
resolved "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz#43700d6d9eecb7419bf086a128d0f7205d9eb665"
@@ -16663,7 +16899,7 @@ immer@8.0.1:
resolved "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656"
integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==
-immer@^9.0.1, immer@^9.0.6:
+immer@^9.0.1, immer@^9.0.7:
version "9.0.7"
resolved "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz#b6156bd7db55db7abc73fd2fdadf4e579a701075"
integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==
@@ -17215,6 +17451,13 @@ is-glob@4.0.1:
dependencies:
is-extglob "^2.1.1"
+is-glob@4.0.3, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
is-glob@^2.0.0:
version "2.0.1"
resolved "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
@@ -17229,13 +17472,6 @@ is-glob@^3.0.0, is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
-is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
- version "4.0.3"
- resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
- integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
- dependencies:
- is-extglob "^2.1.1"
-
is-hexadecimal@^1.0.0:
version "1.0.4"
resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
@@ -18313,7 +18549,7 @@ js-levenshtein@^1.1.6:
resolved "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
-js-string-escape@1.0.1, js-string-escape@^1.0.1:
+js-string-escape@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=
@@ -18604,7 +18840,7 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
-json5@^2.1.2, json5@^2.1.3:
+json5@^2.1.2, json5@^2.1.3, json5@^2.2.0:
version "2.2.0"
resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
@@ -18776,7 +19012,7 @@ jss@10.6.0, jss@^10.5.1:
is-in-browser "^1.1.3"
tiny-warning "^1.0.2"
-"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0:
+"jsx-ast-utils@^2.4.1 || ^3.0.0":
version "3.2.0"
resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82"
integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==
@@ -18784,6 +19020,14 @@ jss@10.6.0, jss@^10.5.1:
array-includes "^3.1.2"
object.assign "^4.1.2"
+jsx-ast-utils@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b"
+ integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==
+ dependencies:
+ array-includes "^3.1.3"
+ object.assign "^4.1.2"
+
junk@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1"
@@ -19283,6 +19527,11 @@ loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
emojis-list "^3.0.0"
json5 "^1.0.1"
+loader-utils@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f"
+ integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==
+
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@@ -19493,11 +19742,6 @@ lodash.throttle@^4.1.1:
resolved "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
-lodash.truncate@^4.4.2:
- version "4.4.2"
- resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
- integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
-
lodash.union@^4.6.0:
version "4.6.0"
resolved "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
@@ -19557,7 +19801,7 @@ log-update@^4.0.0:
slice-ansi "^4.0.0"
wrap-ansi "^6.2.0"
-logform@^2.1.1, logform@^2.2.0:
+logform@^2.2.0:
version "2.3.0"
resolved "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz#a3997a05985de2ebd325ae0d166dffc9c6fe6b57"
integrity sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==
@@ -19568,6 +19812,17 @@ logform@^2.1.1, logform@^2.2.0:
safe-stable-stringify "^1.1.0"
triple-beam "^1.3.0"
+logform@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.npmjs.org/logform/-/logform-2.3.2.tgz#68babe6a74ab09a1fd15a9b1e6cbc7713d41cb5b"
+ integrity sha512-V6JiPThZzTsbVRspNO6TmHkR99oqYTs8fivMBYQkjZj6rxW92KxtDCPE6IkAk1DNBnYKNkjm4jYBm6JDUcyhOA==
+ dependencies:
+ colors "1.4.0"
+ fecha "^4.2.0"
+ ms "^2.1.1"
+ safe-stable-stringify "^1.1.0"
+ triple-beam "^1.3.0"
+
loglevel@^1.6.7:
version "1.6.8"
resolved "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171"
@@ -19806,9 +20061,9 @@ markdown-escapes@^1.0.0:
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
markdown-it@^12.2.0:
- version "12.2.0"
- resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.2.0.tgz#091f720fd5db206f80de7a8d1f1a7035fd0d38db"
- integrity sha512-Wjws+uCrVQRqOoJvze4HCqkKl1AsSh95iFAeQDwnyfxM09divCBSXlDR1uTvyUP3Grzpn4Ru8GeCxYPM8vkCQg==
+ version "12.3.2"
+ resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
+ integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
dependencies:
argparse "^2.0.1"
entities "~2.1.0"
@@ -20485,15 +20740,10 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.49.0:
- version "1.49.0"
- resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed"
- integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==
-
-"mime-db@>= 1.43.0 < 2":
- version "1.48.0"
- resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d"
- integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==
+mime-db@1.51.0, "mime-db@>= 1.43.0 < 2":
+ version "1.51.0"
+ resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c"
+ integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==
mime-db@~1.33.0:
version "1.33.0"
@@ -20508,11 +20758,11 @@ mime-types@2.1.18:
mime-db "~1.33.0"
mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
- version "2.1.32"
- resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5"
- integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==
+ version "2.1.34"
+ resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24"
+ integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==
dependencies:
- mime-db "1.49.0"
+ mime-db "1.51.0"
mime@1.6.0:
version "1.6.0"
@@ -21542,11 +21792,6 @@ oauth@0.9.x:
resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE=
-object-assign@4.1.0:
- version "4.1.0"
- resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
- integrity sha1-ejs9DpgGPUP0wD8uiubNUahog6A=
-
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -21733,7 +21978,7 @@ open@^7.0.2, open@^7.0.3:
is-docker "^2.0.0"
is-wsl "^2.1.1"
-open@^8.0.0, open@^8.0.9:
+open@^8.0.0, open@^8.0.9, open@^8.4.0:
version "8.4.0"
resolved "https://registry.npmjs.org/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
@@ -22039,11 +22284,6 @@ package-json@^6.3.0:
registry-url "^5.0.0"
semver "^6.2.0"
-packet-reader@0.3.1:
- version "0.3.1"
- resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27"
- integrity sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=
-
packet-reader@1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74"
@@ -22539,17 +22779,12 @@ performance-now@^2.1.0:
resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-pg-connection-string@0.1.3, pg-connection-string@^0.1.3:
- version "0.1.3"
- resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7"
- integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=
-
pg-connection-string@2.4.0:
version "2.4.0"
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz#c979922eb47832999a204da5dbe1ebf2341b6a10"
integrity sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==
-pg-connection-string@^2.3.0, pg-connection-string@^2.5.0:
+pg-connection-string@^2.3.0, pg-connection-string@^2.4.0, pg-connection-string@^2.5.0:
version "2.5.0"
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34"
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
@@ -22559,35 +22794,16 @@ pg-int8@1.0.1:
resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
-pg-pool@1.*:
- version "1.8.0"
- resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37"
- integrity sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=
- dependencies:
- generic-pool "2.4.3"
- object-assign "4.1.0"
-
-pg-pool@^3.3.0:
- version "3.3.0"
- resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz#12d5c7f65ea18a6e99ca9811bd18129071e562fc"
- integrity sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==
+pg-pool@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz#0e71ce2c67b442a5e862a9c182172c37eda71e9c"
+ integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==
pg-protocol@^1.5.0:
version "1.5.0"
resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz#b5dd452257314565e2d54ab3c132adc46565a6a0"
integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==
-pg-types@1.*:
- version "1.13.0"
- resolved "https://registry.npmjs.org/pg-types/-/pg-types-1.13.0.tgz#75f490b8a8abf75f1386ef5ec4455ecf6b345c63"
- integrity sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==
- dependencies:
- pg-int8 "1.0.1"
- postgres-array "~1.0.0"
- postgres-bytea "~1.0.0"
- postgres-date "~1.0.0"
- postgres-interval "^1.1.0"
-
pg-types@^2.1.0:
version "2.2.0"
resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
@@ -22599,34 +22815,20 @@ pg-types@^2.1.0:
postgres-date "~1.0.4"
postgres-interval "^1.1.0"
-pg@^6.1.0:
- version "6.4.2"
- resolved "https://registry.npmjs.org/pg/-/pg-6.4.2.tgz#c364011060eac7a507a2ae063eb857ece910e27f"
- integrity sha1-w2QBEGDqx6UHoq4GPrhX7OkQ4n8=
- dependencies:
- buffer-writer "1.0.1"
- js-string-escape "1.0.1"
- packet-reader "0.3.1"
- pg-connection-string "0.1.3"
- pg-pool "1.*"
- pg-types "1.*"
- pgpass "1.*"
- semver "4.3.2"
-
-pg@^8.3.0:
- version "8.6.0"
- resolved "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz#e222296b0b079b280cce106ea991703335487db2"
- integrity sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==
+pg@^8.3.0, pg@^8.4.0:
+ version "8.7.1"
+ resolved "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz#9ea9d1ec225980c36f94e181d009ab9f4ce4c471"
+ integrity sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==
dependencies:
buffer-writer "2.0.0"
packet-reader "1.0.0"
pg-connection-string "^2.5.0"
- pg-pool "^3.3.0"
+ pg-pool "^3.4.1"
pg-protocol "^1.5.0"
pg-types "^2.1.0"
pgpass "1.x"
-pgpass@1.*, pgpass@1.x:
+pgpass@1.x:
version "1.0.2"
resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306"
integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=
@@ -22634,13 +22836,13 @@ pgpass@1.*, pgpass@1.x:
split "^1.0.0"
pgtools@^0.3.0:
- version "0.3.0"
- resolved "https://registry.npmjs.org/pgtools/-/pgtools-0.3.0.tgz#ee7decf4183ada28299c63df71e1e73c95b5bc53"
- integrity sha512-8NxDCJ8xJ6hOp9hVNZqxi+TZl7hM1Jc8pQyj8DlAbyaWnk5OsGwf3gB/UyDODdOguiim9QzbzPsslp//apO+Uw==
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/pgtools/-/pgtools-0.3.2.tgz#df11d54057c889e27ba891664efda69de1b7a0fe"
+ integrity sha512-o9iI8CrJohpjt3hgoJuEC18oYrt/iLsc3BYtW6kP/0T7EyQ9T/WlnuzyKcC2GtfutREfXCmwaUcbqPrLw8sjng==
dependencies:
bluebird "^3.3.5"
- pg "^6.1.0"
- pg-connection-string "^0.1.3"
+ pg "^8.4.0"
+ pg-connection-string "^2.4.0"
yargs "^5.0.0"
picocolors@^1.0.0:
@@ -23155,11 +23357,6 @@ postcss@^8.1.0, postcss@^8.2.15:
nanoid "^3.1.23"
source-map-js "^0.6.2"
-postgres-array@~1.0.0:
- version "1.0.3"
- resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz#c561fc3b266b21451fc6555384f4986d78ec80f5"
- integrity sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==
-
postgres-array@~2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
@@ -23170,7 +23367,7 @@ postgres-bytea@~1.0.0:
resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=
-postgres-date@~1.0.0, postgres-date@~1.0.4:
+postgres-date@~1.0.4:
version "1.0.5"
resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz#710b27de5f27d550f6e80b5d34f7ba189213c2ee"
integrity sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==
@@ -23385,7 +23582,7 @@ prompts@2.4.0:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prompts@^2.0.1, prompts@^2.4.0:
+prompts@^2.0.1, prompts@^2.4.0, prompts@^2.4.2:
version "2.4.2"
resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
@@ -23421,14 +23618,7 @@ property-expr@^2.0.4:
resolved "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910"
integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==
-property-information@^5.0.0:
- version "5.4.0"
- resolved "https://registry.npmjs.org/property-information/-/property-information-5.4.0.tgz#16e08f13f4e5c4a7be2e4ec431c01c4f8dba869a"
- integrity sha512-nmMWAm/3vKFGmmOWOcdLjgq/Hlxa+hsuR/px1Lp/UGEyc5A22A6l78Shc2C0E71sPmAqglni+HrS7L7VJ7AUCA==
- dependencies:
- xtend "^4.0.0"
-
-property-information@^5.3.0:
+property-information@^5.0.0, property-information@^5.3.0:
version "5.6.0"
resolved "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69"
integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==
@@ -23837,33 +24027,33 @@ react-dev-utils@^11.0.3:
text-table "0.2.0"
react-dev-utils@^12.0.0-next.47:
- version "12.0.0-next.47"
- resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0-next.47.tgz#e55c31a05eb30cfd69ca516e8b87d61724e880fb"
- integrity sha512-PsE71vP15TZMmp/RZKOJC4fYD5Pvt0+wCoyG3QHclto0d4FyIJI78xGRICOOThZFROqgXYlZP6ddmeybm+jO4w==
+ version "12.0.0"
+ resolved "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526"
+ integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ==
dependencies:
- "@babel/code-frame" "^7.10.4"
+ "@babel/code-frame" "^7.16.0"
address "^1.1.2"
- browserslist "^4.16.5"
- chalk "^2.4.2"
+ browserslist "^4.18.1"
+ chalk "^4.1.2"
cross-spawn "^7.0.3"
detect-port-alt "^1.1.6"
- escape-string-regexp "^2.0.0"
- filesize "^6.1.0"
- find-up "^4.1.0"
- fork-ts-checker-webpack-plugin "^6.0.5"
+ escape-string-regexp "^4.0.0"
+ filesize "^8.0.6"
+ find-up "^5.0.0"
+ fork-ts-checker-webpack-plugin "^6.5.0"
global-modules "^2.0.0"
- globby "^11.0.1"
- gzip-size "^5.1.1"
- immer "^9.0.6"
+ globby "^11.0.4"
+ gzip-size "^6.0.0"
+ immer "^9.0.7"
is-root "^2.1.0"
- loader-utils "^2.0.0"
- open "^7.0.2"
+ loader-utils "^3.2.0"
+ open "^8.4.0"
pkg-up "^3.1.0"
- prompts "^2.4.0"
- react-error-overlay "7.0.0-next.54+1465357b"
+ prompts "^2.4.2"
+ react-error-overlay "^6.0.10"
recursive-readdir "^2.2.2"
- shell-quote "^1.7.2"
- strip-ansi "^6.0.0"
+ shell-quote "^1.7.3"
+ strip-ansi "^6.0.1"
text-table "^0.2.0"
react-docgen-typescript@^2.0.0:
@@ -23915,15 +24105,10 @@ react-error-boundary@^3.1.0:
dependencies:
"@babel/runtime" "^7.12.5"
-react-error-overlay@7.0.0-next.54+1465357b:
- version "7.0.0-next.54"
- resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-7.0.0-next.54.tgz#c1eb5ab86aee15e9552e6d97897b08f2bd06d140"
- integrity sha512-b96CiTnZahXPDNH9MKplvt5+jD+BkxDw7q5R3jnkUXze/ux1pLv32BBZmlj0OfCUeMqyz4sAmF+0ccJGVMlpXw==
-
-react-error-overlay@^6.0.9:
- version "6.0.9"
- resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
- integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
+react-error-overlay@^6.0.10, react-error-overlay@^6.0.9:
+ version "6.0.10"
+ resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6"
+ integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==
react-fast-compare@^3.0.1, react-fast-compare@^3.1.1, react-fast-compare@^3.2.0:
version "3.2.0"
@@ -24017,13 +24202,14 @@ react-lifecycles-compat@^3.0.4:
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-markdown@^7.0.1:
- version "7.0.1"
- resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-7.0.1.tgz#c7365fcd7d1813b3ae68f2200e8f92d47d865627"
- integrity sha512-pthNPaoiwg0q7hukoE04F2ENwSzijIlWHJ4UMs/96LUe/G/P3FnbP4qHzx3FoNqae+2SqDG8vzniTLnJDeWneg==
+ version "7.1.2"
+ resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-7.1.2.tgz#c9fa9d1c87e24529f028e1cdf731e81ccdd8e547"
+ integrity sha512-ibMcc0EbfmbwApqJD8AUr0yls8BSrKzIbHaUsPidQljxToCqFh34nwtu3CXNEItcVJNzpjDHrhK8A+MAh2JW3A==
dependencies:
"@types/hast" "^2.0.0"
"@types/unist" "^2.0.0"
comma-separated-tokens "^2.0.0"
+ hast-util-whitespace "^2.0.0"
prop-types "^15.0.0"
property-information "^6.0.0"
react-is "^17.0.0"
@@ -24620,10 +24806,10 @@ regexp.prototype.flags@^1.3.1:
call-bind "^1.0.2"
define-properties "^1.1.3"
-regexpp@^3.1.0:
- version "3.1.0"
- resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
- integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
+regexpp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+ integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
regexpu-core@^4.7.1:
version "4.7.1"
@@ -24673,35 +24859,37 @@ relateurl@^0.2.7:
resolved "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=
-relay-compiler@10.1.0:
- version "10.1.0"
- resolved "https://registry.npmjs.org/relay-compiler/-/relay-compiler-10.1.0.tgz#fb4672cdbe9b54869a3a79759edd8c2d91609cbe"
- integrity sha512-HPqc3N3tNgEgUH5+lTr5lnLbgnsZMt+MRiyS0uAVNhuPY2It0X1ZJG+9qdA3L9IqKFUNwVn6zTO7RArjMZbARQ==
+relay-compiler@12.0.0:
+ version "12.0.0"
+ resolved "https://registry.npmjs.org/relay-compiler/-/relay-compiler-12.0.0.tgz#9f292d483fb871976018704138423a96c8a45439"
+ integrity sha512-SWqeSQZ+AMU/Cr7iZsHi1e78Z7oh00I5SvR092iCJq79aupqJ6Ds+I1Pz/Vzo5uY5PY0jvC4rBJXzlIN5g9boQ==
dependencies:
- "@babel/core" "^7.0.0"
- "@babel/generator" "^7.5.0"
- "@babel/parser" "^7.0.0"
+ "@babel/core" "^7.14.0"
+ "@babel/generator" "^7.14.0"
+ "@babel/parser" "^7.14.0"
"@babel/runtime" "^7.0.0"
- "@babel/traverse" "^7.0.0"
+ "@babel/traverse" "^7.14.0"
"@babel/types" "^7.0.0"
- babel-preset-fbjs "^3.3.0"
+ babel-preset-fbjs "^3.4.0"
chalk "^4.0.0"
fb-watchman "^2.0.0"
fbjs "^3.0.0"
glob "^7.1.1"
immutable "~3.7.6"
+ invariant "^2.2.4"
nullthrows "^1.1.1"
- relay-runtime "10.1.0"
+ relay-runtime "12.0.0"
signedsource "^1.0.0"
yargs "^15.3.1"
-relay-runtime@10.1.0:
- version "10.1.0"
- resolved "https://registry.npmjs.org/relay-runtime/-/relay-runtime-10.1.0.tgz#4753bf36e95e8d862cef33608e3d98b4ed730d16"
- integrity sha512-bxznLnQ1ST6APN/cFi7l0FpjbZVchWQjjhj9mAuJBuUqNNCh9uV+UTRhpQF7Q8ycsPp19LHTpVyGhYb0ustuRQ==
+relay-runtime@12.0.0:
+ version "12.0.0"
+ resolved "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz#1e039282bdb5e0c1b9a7dc7f6b9a09d4f4ff8237"
+ integrity sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==
dependencies:
"@babel/runtime" "^7.0.0"
fbjs "^3.0.0"
+ invariant "^2.2.4"
remark-footnotes@2.0.0:
version "2.0.0"
@@ -25119,13 +25307,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
inherits "^2.0.1"
rollup-plugin-dts@^4.0.1:
- version "4.0.1"
- resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.0.1.tgz#930cbd5aaaa64a55e895ecd6ae8234e1a5467710"
- integrity sha512-DNv5F8pro/r0Hkx3JWKRtJZocDnqXfgypoajeiaNq134rYaFcEIl/oas5PogD1qexMadVijsHyVko1Chig0OOQ==
+ version "4.1.0"
+ resolved "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-4.1.0.tgz#63b1e7de3970bb6d50877e60df2150a3892bc49c"
+ integrity sha512-rriXIm3jdUiYeiAAd1Fv+x2AxK6Kq6IybB2Z/IdoAW95fb4uRUurYsEYKa8L1seedezDeJhy8cfo8FEL9aZzqg==
dependencies:
magic-string "^0.25.7"
optionalDependencies:
- "@babel/code-frame" "^7.14.5"
+ "@babel/code-frame" "^7.16.0"
rollup-plugin-esbuild@^4.7.2:
version "4.7.2"
@@ -25416,11 +25604,6 @@ semver-store@^0.3.0:
resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
-semver@4.3.2:
- version "4.3.2"
- resolved "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7"
- integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=
-
semver@7.0.0:
version "7.0.0"
resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
@@ -25656,7 +25839,7 @@ shell-quote@1.7.2:
resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
-shell-quote@^1.7.2:
+shell-quote@^1.7.3:
version "1.7.3"
resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123"
integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==
@@ -25907,7 +26090,7 @@ sort-keys@^4.0.0:
dependencies:
is-plain-obj "^2.0.0"
-source-list-map@^2.0.0:
+source-list-map@^2.0.0, source-list-map@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
@@ -26497,7 +26680,7 @@ strip-ansi@5.2.0, strip-ansi@^5.1.0:
dependencies:
ansi-regex "^4.1.0"
-strip-ansi@6.0.0, strip-ansi@^6.0.0:
+strip-ansi@6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
@@ -26518,7 +26701,7 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
-strip-ansi@^6.0.1:
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -26741,14 +26924,7 @@ supports-color@^6.1.0:
dependencies:
has-flag "^3.0.0"
-supports-color@^7.0.0, supports-color@^7.1.0:
- version "7.1.0"
- resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
- integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
- dependencies:
- has-flag "^4.0.0"
-
-supports-color@^7.2.0:
+supports-color@^7.0.0, supports-color@^7.1.0, supports-color@^7.2.0:
version "7.2.0"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
@@ -26900,7 +27076,7 @@ sync-fetch@0.3.0:
buffer "^5.7.0"
node-fetch "^2.6.1"
-sync-fetch@0.3.1:
+sync-fetch@0.3.1, sync-fetch@^0.3.1:
version "0.3.1"
resolved "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.3.1.tgz#62aa82c4b4d43afd6906bfd7b5f92056458509f0"
integrity sha512-xj5qiCDap/03kpci5a+qc5wSJjc8ZSixgG2EUmH1B8Ea2sfWclQA7eH40hiHPCtkCn6MCk4Wb+dqcXdCy2PP3g==
@@ -26908,18 +27084,6 @@ sync-fetch@0.3.1:
buffer "^5.7.0"
node-fetch "^2.6.1"
-table@^6.0.9:
- version "6.7.1"
- resolved "https://registry.npmjs.org/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2"
- integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==
- dependencies:
- ajv "^8.0.1"
- lodash.clonedeep "^4.5.0"
- lodash.truncate "^4.4.2"
- slice-ansi "^4.0.0"
- string-width "^4.2.0"
- strip-ansi "^6.0.0"
-
tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
@@ -27593,7 +27757,7 @@ ts-pnp@^1.1.6:
resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
-tsconfig-paths@^3.11.0:
+tsconfig-paths@^3.12.0:
version "3.12.0"
resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==
@@ -27623,6 +27787,11 @@ tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0,
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
+tslib@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
+ integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
+
tslib@~2.0.1:
version "2.0.3"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
@@ -28492,7 +28661,7 @@ validator@^13.7.0:
resolved "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
-value-or-promise@1.0.11:
+value-or-promise@1.0.11, value-or-promise@^1.0.11:
version "1.0.11"
resolved "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140"
integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==
@@ -28811,6 +28980,14 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
source-list-map "^2.0.0"
source-map "~0.6.1"
+webpack-sources@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
+ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
+ dependencies:
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
webpack-sources@^3.2.0:
version "3.2.0"
resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
@@ -29175,20 +29352,20 @@ write-pkg@^4.0.0:
type-fest "^0.4.1"
write-json-file "^3.2.0"
-ws@7.4.5, ws@^7.4.6:
- version "7.5.6"
- resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b"
- integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==
+ws@7.4.5:
+ version "7.4.5"
+ resolved "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1"
+ integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==
ws@7.4.6:
version "7.4.6"
resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c"
integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==
-ws@8.3.0:
- version "8.3.0"
- resolved "https://registry.npmjs.org/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d"
- integrity sha512-Gs5EZtpqZzLvmIM59w4igITU57lrtYVFneaa434VROv4thzJyV6UjIL3D42lslWlI+D4KzLYnxSwtfuiO79sNw==
+ws@8.3.0, ws@^7.4.6, ws@^8.3.0:
+ version "7.5.6"
+ resolved "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b"
+ integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==
"ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.2.3, ws@^7.3.1:
version "7.5.0"
@@ -29395,20 +29572,7 @@ yargs@^16.1.1, yargs@^16.2.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
-yargs@^17.0.0, yargs@^17.0.1, yargs@^17.1.1:
- version "17.2.1"
- resolved "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea"
- integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==
- dependencies:
- cliui "^7.0.2"
- escalade "^3.1.1"
- get-caller-file "^2.0.5"
- require-directory "^2.1.1"
- string-width "^4.2.0"
- y18n "^5.0.5"
- yargs-parser "^20.2.2"
-
-yargs@^17.3.0:
+yargs@^17.0.0, yargs@^17.0.1, yargs@^17.1.1, yargs@^17.3.0:
version "17.3.0"
resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz#295c4ffd0eef148ef3e48f7a2e0f58d0e4f26b1c"
integrity sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==