diff --git a/.changeset/late-walls-cry.md b/.changeset/late-walls-cry.md
new file mode 100644
index 0000000000..c9fcb3112a
--- /dev/null
+++ b/.changeset/late-walls-cry.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-search-backend-module-elasticsearch': patch
+---
+
+Pinning version of elastic search client to 7.13.0 to prevent breaking change towards third party ElasticSearch clusters on 7.14.0.
diff --git a/.changeset/neat-pugs-wait.md b/.changeset/neat-pugs-wait.md
new file mode 100644
index 0000000000..8902f44c9d
--- /dev/null
+++ b/.changeset/neat-pugs-wait.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-code-coverage': patch
+---
+
+Change represented test date from epoch to something more human friendly. Round test coverage to 2 decimal places.
diff --git a/.changeset/odd-rats-walk.md b/.changeset/odd-rats-walk.md
new file mode 100644
index 0000000000..3a8710cc32
--- /dev/null
+++ b/.changeset/odd-rats-walk.md
@@ -0,0 +1,5 @@
+---
+'@backstage/config-loader': patch
+---
+
+Bump msw to the same version as the rest
diff --git a/.changeset/real-mails-add.md b/.changeset/real-mails-add.md
new file mode 100644
index 0000000000..30a9100699
--- /dev/null
+++ b/.changeset/real-mails-add.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+fixed route resolving (issue #7741) when user cannot select a tab in any of the tabbed pages (like the Catalog page) if it shares the same initial letters as a preceding tab. (i.e. where tab with a path of /ci is followed by a path of /ci-2, user cannot select /ci-2 as /ci will always be selected first).
diff --git a/.changeset/slimy-days-leave.md b/.changeset/slimy-days-leave.md
new file mode 100644
index 0000000000..df772d80d4
--- /dev/null
+++ b/.changeset/slimy-days-leave.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-backend': patch
+---
+
+Allow singleton and flexibly nested EntityFilters
diff --git a/.changeset/smart-penguins-compete.md b/.changeset/smart-penguins-compete.md
new file mode 100644
index 0000000000..d3518600a6
--- /dev/null
+++ b/.changeset/smart-penguins-compete.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+export `loadIdentityOwnerRefs` and `loadCatalogOwnerRefs` all the way
diff --git a/.changeset/tall-boxes-sit.md b/.changeset/tall-boxes-sit.md
new file mode 100644
index 0000000000..a74e0400bd
--- /dev/null
+++ b/.changeset/tall-boxes-sit.md
@@ -0,0 +1,5 @@
+---
+'@backstage/core-components': patch
+---
+
+Add Theme Overrides for Sidebar
diff --git a/.changeset/tough-buckets-explain.md b/.changeset/tough-buckets-explain.md
new file mode 100644
index 0000000000..a2ca37d516
--- /dev/null
+++ b/.changeset/tough-buckets-explain.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-azure-devops': patch
+---
+
+Simplified queue time calculation in `BuildTable`.
diff --git a/.github/workflows/snyk-github-issue-sync.yml b/.github/workflows/snyk-github-issue-sync.yml
new file mode 100644
index 0000000000..34eb5c1ca4
--- /dev/null
+++ b/.github/workflows/snyk-github-issue-sync.yml
@@ -0,0 +1,23 @@
+name: 'Snyk Github Issue Sync'
+
+on:
+ schedule:
+ - cron: '0 */4 * * *'
+
+jobs:
+ sync:
+ steps:
+ - uses: actions/checkout@v2
+ - name: Create Snyk report
+ uses: snyk/actions/node@master
+ with:
+ args: >
+ --yarn-workspaces
+ --org=backstage-dgh
+ --strict-out-of-sync=false
+ --json-file-output=snyk.json
+ json: true
+ env:
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
+ - name: Update Github issues
+ run: yarn ts-node scripts/snyk-github-issue-sync.ts
diff --git a/ADOPTERS.md b/ADOPTERS.md
index 06501a2a10..f0b2fa16f6 100644
--- a/ADOPTERS.md
+++ b/ADOPTERS.md
@@ -63,3 +63,4 @@
| [Splunk](https://www.splunk.com) | [@tonytamsf](https://github.com/tonytamsf) | Developer portal as a centralized place to find people, services, documentation, escalation policies and give bravos. This portal is also being used as a centralized search engine for engineering specific documentation. |
| [SoundCloud](https://www.soundcloud.com) | [Julio Zynger](https://github.com/julioz) | Developer portal as a [humane registry](https://martinfowler.com/bliki/HumaneRegistry.html) for the organization: catalog of people, services, documentation, feature toggles, escalation policies, etc. |
| [Volvofinans Bank](https://www.volvofinans.se) | [Johan Hammar](https://github.com/johanhammar) | Developer portal enabling engineers to manage and explore software and documentation. |
+| [Palo Alto Networks](https://www.paloaltonetworks.com) | [Jeremy Guarini](https://github.com/jeremyguarini), [Brian Lomeland](https://github.com/bbbmmmlll), [Palo Alto Networks](https://github.com/PaloAltoNetworks) | Developer portal, service catalog, documentation and tooling |
diff --git a/microsite/sidebars.json b/microsite/sidebars.json
index bee9cd7180..23cc6135c0 100644
--- a/microsite/sidebars.json
+++ b/microsite/sidebars.json
@@ -275,7 +275,8 @@
"architecture-decisions/adrs-adr008",
"architecture-decisions/adrs-adr009",
"architecture-decisions/adrs-adr010",
- "architecture-decisions/adrs-adr011"
+ "architecture-decisions/adrs-adr011",
+ "architecture-decisions/adrs-adr012"
],
"FAQ": ["FAQ"]
}
diff --git a/package.json b/package.json
index f5d20fd39d..62a8a0924e 100644
--- a/package.json
+++ b/package.json
@@ -58,9 +58,10 @@
"@microsoft/tsdoc": "^0.13.2"
},
"devDependencies": {
- "@types/webpack": "^5.28.0",
"@changesets/cli": "^2.14.0",
+ "@octokit/rest": "^18.12.0",
"@spotify/prettier-config": "^11.0.0",
+ "@types/webpack": "^5.28.0",
"command-exists": "^1.2.9",
"concurrently": "^6.0.0",
"eslint-plugin-notice": "^0.9.10",
@@ -68,6 +69,7 @@
"husky": "^6.0.0",
"lerna": "^4.0.0",
"lint-staged": "^11.1.2",
+ "minimist": "^1.2.5",
"prettier": "^2.2.1",
"shx": "^0.3.2",
"yarn-lock-check": "^1.0.5"
diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json
index 910dd87108..22fcedf486 100644
--- a/packages/config-loader/package.json
+++ b/packages/config-loader/package.json
@@ -53,7 +53,7 @@
"@types/node": "^14.14.32",
"@types/yup": "^0.29.13",
"mock-fs": "^5.1.0",
- "msw": "^0.29.0"
+ "msw": "^0.35.0"
},
"files": [
"dist"
diff --git a/packages/core-components/src/components/TabbedLayout/RoutedTabs.test.tsx b/packages/core-components/src/components/TabbedLayout/RoutedTabs.test.tsx
index 9b33304a95..bbd48c127c 100644
--- a/packages/core-components/src/components/TabbedLayout/RoutedTabs.test.tsx
+++ b/packages/core-components/src/components/TabbedLayout/RoutedTabs.test.tsx
@@ -31,6 +31,12 @@ const testRoute2 = {
children:
tabbed-test-content-2
,
};
+const testRoute3 = {
+ title: 'tabbed-test-title-3',
+ path: '/some-other-path-similar',
+ children: tabbed-test-content-3
,
+};
+
describe('RoutedTabs', () => {
it('renders simplest case', async () => {
const rendered = await renderInTestApp(
@@ -46,7 +52,7 @@ describe('RoutedTabs', () => {
}
+ element={}
/>
,
);
@@ -61,6 +67,13 @@ describe('RoutedTabs', () => {
expect(rendered.getByText('tabbed-test-title-2')).toBeInTheDocument();
expect(rendered.queryByText('tabbed-test-content-2')).toBeInTheDocument();
+
+ const thirdTab = rendered.queryAllByRole('tab')[2];
+ act(() => {
+ fireEvent.click(thirdTab);
+ });
+ expect(rendered.getByText('tabbed-test-title-3')).toBeInTheDocument();
+ expect(rendered.queryByText('tabbed-test-content-3')).toBeInTheDocument();
});
describe('correctly delegates nested links', () => {
diff --git a/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx b/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx
index 2a65c8ffc8..5debafd3f8 100644
--- a/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx
+++ b/packages/core-components/src/components/TabbedLayout/RoutedTabs.tsx
@@ -33,9 +33,15 @@ export function useSelectedSubRoute(subRoutes: SubRoute[]): {
element: children,
}));
- const element = useRoutes(routes) ?? subRoutes[0].children;
+ // TODO: remove once react-router updated
+ const sortedRoutes = routes.sort((a, b) =>
+ // remove "/*" symbols from path end before comparing
+ b.path.replace(/\/\*$/, '').localeCompare(a.path.replace(/\/\*$/, '')),
+ );
- const [matchedRoute] = matchRoutes(routes, `/${params['*']}`) ?? [];
+ const element = useRoutes(sortedRoutes) ?? subRoutes[0].children;
+
+ const [matchedRoute] = matchRoutes(sortedRoutes, `/${params['*']}`) ?? [];
const foundIndex = matchedRoute
? subRoutes.findIndex(t => `${t.path}/*` === matchedRoute.route.path)
: 0;
diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx
index 883e0395cd..ed089ad6a1 100644
--- a/packages/core-components/src/layout/Sidebar/Items.tsx
+++ b/packages/core-components/src/layout/Sidebar/Items.tsx
@@ -350,21 +350,30 @@ export function SidebarSearchField(props: SidebarSearchFieldProps) {
);
}
-export const SidebarSpace = styled('div')({
- flex: 1,
-});
+export const SidebarSpace = styled('div')(
+ {
+ flex: 1,
+ },
+ { name: 'BackstageSidebarSpace' },
+);
-export const SidebarSpacer = styled('div')({
- height: 8,
-});
+export const SidebarSpacer = styled('div')(
+ {
+ height: 8,
+ },
+ { name: 'BackstageSidebarSpacer' },
+);
-export const SidebarDivider = styled('hr')({
- height: 1,
- width: '100%',
- background: '#383838',
- border: 'none',
- margin: '12px 0px',
-});
+export const SidebarDivider = styled('hr')(
+ {
+ height: 1,
+ width: '100%',
+ background: '#383838',
+ border: 'none',
+ margin: '12px 0px',
+ },
+ { name: 'BackstageSidebarDivider' },
+);
const styledScrollbar = (theme: Theme): CreateCSSProperties => ({
overflowY: 'auto',
diff --git a/plugins/azure-devops-common/.eslintrc.js b/plugins/azure-devops-common/.eslintrc.js
new file mode 100644
index 0000000000..13573efa9c
--- /dev/null
+++ b/plugins/azure-devops-common/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: [require.resolve('@backstage/cli/config/eslint')],
+};
diff --git a/plugins/azure-devops-common/api-report.md b/plugins/azure-devops-common/api-report.md
new file mode 100644
index 0000000000..0bc6568189
--- /dev/null
+++ b/plugins/azure-devops-common/api-report.md
@@ -0,0 +1,47 @@
+## API Report File for "@backstage/plugin-azure-devops-common"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+// Warning: (ae-missing-release-tag) "BuildResult" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export enum BuildResult {
+ Canceled = 32,
+ Failed = 8,
+ None = 0,
+ PartiallySucceeded = 4,
+ Succeeded = 2,
+}
+
+// Warning: (ae-missing-release-tag) "BuildStatus" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export enum BuildStatus {
+ All = 47,
+ Cancelling = 4,
+ Completed = 2,
+ InProgress = 1,
+ None = 0,
+ NotStarted = 32,
+ Postponed = 8,
+}
+
+// Warning: (ae-missing-release-tag) "RepoBuild" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export type RepoBuild = {
+ id?: number;
+ title: string;
+ link?: string;
+ status?: BuildStatus;
+ result?: BuildResult;
+ queueTime?: Date;
+ startTime?: Date;
+ finishTime?: Date;
+ source: string;
+ uniqueName?: string;
+};
+
+// (No @packageDocumentation comment for this package)
+```
diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json
new file mode 100644
index 0000000000..05f70f6596
--- /dev/null
+++ b/plugins/azure-devops-common/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "@backstage/plugin-azure-devops-common",
+ "version": "0.0.1",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "private": false,
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.cjs.js",
+ "module": "dist/index.esm.js",
+ "types": "dist/index.d.ts"
+ },
+ "homepage": "https://backstage.io",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/backstage/backstage",
+ "directory": "plugins/azure-devops-common"
+ },
+ "keywords": [
+ "backstage"
+ ],
+ "scripts": {
+ "build": "backstage-cli build",
+ "lint": "backstage-cli lint",
+ "test": "backstage-cli test --passWithNoTests",
+ "prepack": "backstage-cli prepack",
+ "postpack": "backstage-cli postpack",
+ "clean": "backstage-cli clean"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.8.1"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/azure-devops-common/src/index.ts b/plugins/azure-devops-common/src/index.ts
new file mode 100644
index 0000000000..26a854de89
--- /dev/null
+++ b/plugins/azure-devops-common/src/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 './types';
diff --git a/plugins/azure-devops-common/src/types.ts b/plugins/azure-devops-common/src/types.ts
new file mode 100644
index 0000000000..d7736d03e1
--- /dev/null
+++ b/plugins/azure-devops-common/src/types.ts
@@ -0,0 +1,82 @@
+/*
+ * 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 enum BuildResult {
+ /**
+ * No result
+ */
+ None = 0,
+ /**
+ * The build completed successfully.
+ */
+ Succeeded = 2,
+ /**
+ * The build completed compilation successfully but had other errors.
+ */
+ PartiallySucceeded = 4,
+ /**
+ * The build completed unsuccessfully.
+ */
+ Failed = 8,
+ /**
+ * The build was canceled before starting.
+ */
+ Canceled = 32,
+}
+
+export enum BuildStatus {
+ /**
+ * No status.
+ */
+ None = 0,
+ /**
+ * The build is currently in progress.
+ */
+ InProgress = 1,
+ /**
+ * The build has completed.
+ */
+ Completed = 2,
+ /**
+ * The build is cancelling
+ */
+ Cancelling = 4,
+ /**
+ * The build is inactive in the queue.
+ */
+ Postponed = 8,
+ /**
+ * The build has not yet started.
+ */
+ NotStarted = 32,
+ /**
+ * All status.
+ */
+ All = 47,
+}
+
+export type RepoBuild = {
+ id?: number;
+ title: string;
+ link?: string;
+ status?: BuildStatus;
+ result?: BuildResult;
+ queueTime?: Date;
+ startTime?: Date;
+ finishTime?: Date;
+ source: string;
+ uniqueName?: string;
+};
diff --git a/plugins/azure-devops/src/components/BuildTable/BuildTable.stories.tsx b/plugins/azure-devops/src/components/BuildTable/BuildTable.stories.tsx
new file mode 100644
index 0000000000..76a19155ba
--- /dev/null
+++ b/plugins/azure-devops/src/components/BuildTable/BuildTable.stories.tsx
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {
+ BuildResult,
+ BuildStatus,
+ RepoBuild,
+} from '@backstage/plugin-azure-devops-common';
+
+import { BuildTable } from './BuildTable';
+import { MemoryRouter } from 'react-router';
+import React from 'react';
+
+export default {
+ title: 'Plugins/Azure Devops/Build Table',
+ component: BuildTable,
+};
+
+const buildStatuses: Array<[BuildStatus, BuildResult]> = [
+ [BuildStatus.InProgress, BuildResult.None], // In Progress
+ [BuildStatus.Completed, BuildResult.Succeeded], // Succeeded
+ [BuildStatus.Completed, BuildResult.Failed], // Failed
+ [BuildStatus.Completed, BuildResult.PartiallySucceeded], // Partially Succeeded
+ [BuildStatus.Completed, BuildResult.Canceled], // Cancelled
+ [BuildStatus.Completed, BuildResult.None], // Unknown
+ [BuildStatus.Cancelling, BuildResult.None], // Cancelling
+ [BuildStatus.Postponed, BuildResult.None], // Postponed
+ [BuildStatus.NotStarted, BuildResult.None], // Not Started
+ [BuildStatus.None, BuildResult.None], // Unknown
+];
+
+const generateTestData = (rows = 10): RepoBuild[] => {
+ const repoBuilds: RepoBuild[] = [];
+
+ for (let i = 0; i < rows; i++) {
+ const [status, result] = buildStatuses[i] ?? [
+ BuildStatus.Completed,
+ BuildResult.Succeeded,
+ ];
+
+ repoBuilds.push({
+ id: rows - i + 12534,
+ title: `backstage ci - 1.0.0-preview-${rows - i}`,
+ status,
+ result,
+ queueTime: new Date(Date.now() - i * 60000),
+ source: 'refs/heads/main',
+ link: '',
+ });
+ }
+
+ return repoBuilds;
+};
+
+export const Default = () => (
+
+
+
+);
+
+export const Empty = () => (
+
+
+
+);
+
+export const Loading = () => (
+
+
+
+);
+
+export const ErrorMessage = () => (
+
+
+
+);
diff --git a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
index 7e260be6e9..5667c65711 100644
--- a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
+++ b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
@@ -149,9 +149,7 @@ const columns: TableColumn[] = [
field: 'queueTime',
width: 'auto',
render: (row: Partial) =>
- DateTime.fromISO(
- row.queueTime ? row.queueTime.toString() : new Date().toString(),
- ).toRelative(),
+ DateTime.fromJSDate(row.queueTime ?? new Date()).toRelative(),
},
];
diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md
index 6d21884c12..143e31bc21 100644
--- a/plugins/catalog-backend/api-report.md
+++ b/plugins/catalog-backend/api-report.md
@@ -870,11 +870,14 @@ export type EntityAncestryResponse = {
// Warning: (ae-missing-release-tag) "EntityFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
-export type EntityFilter = {
- anyOf: {
- allOf: EntitiesSearchFilter[];
- }[];
-};
+export type EntityFilter =
+ | {
+ allOf: EntityFilter[];
+ }
+ | {
+ anyOf: EntityFilter[];
+ }
+ | EntitiesSearchFilter;
// Warning: (ae-missing-release-tag) "EntityPagination" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts
index 0bc0ec4311..df693bfd42 100644
--- a/plugins/catalog-backend/src/catalog/types.ts
+++ b/plugins/catalog-backend/src/catalog/types.ts
@@ -22,9 +22,10 @@ import { Entity, EntityRelationSpec } from '@backstage/catalog-model';
* Any (at least one) of the outer sets must match, within which all of the
* individual filters must match.
*/
-export type EntityFilter = {
- anyOf: { allOf: EntitiesSearchFilter[] }[];
-};
+export type EntityFilter =
+ | { allOf: EntityFilter[] }
+ | { anyOf: EntityFilter[] }
+ | EntitiesSearchFilter;
/**
* A pagination rule for entities.
diff --git a/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts b/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts
index 5cc31b5be5..6a150f7583 100644
--- a/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts
+++ b/plugins/catalog-backend/src/legacy/database/CommonDatabase.ts
@@ -46,7 +46,11 @@ import {
DbPageInfo,
Transaction,
} from './types';
-import { EntityPagination } from '../../catalog/types';
+import { EntityPagination, EntitiesSearchFilter } from '../../catalog/types';
+
+type LegacyEntityFilter = {
+ anyOf: { allOf: EntitiesSearchFilter[] }[];
+};
// The number of items that are sent per batch to the database layer, when
// doing .batchInsert calls to knex. This needs to be low enough to not cause
@@ -217,13 +221,28 @@ export class CommonDatabase implements Database {
let entitiesQuery = tx('entities');
- for (const singleFilter of request?.filter?.anyOf ?? []) {
+ if (
+ request?.filter &&
+ (request.filter.hasOwnProperty('key') ||
+ request.filter.hasOwnProperty('allOf'))
+ ) {
+ throw new Error(
+ 'Filters for the legacy CommonDatabase must obey the { anyOf: [{ allOf: [] }] } format.',
+ );
+ }
+ for (const singleFilter of (request?.filter as LegacyEntityFilter)?.anyOf ??
+ []) {
entitiesQuery = entitiesQuery.orWhere(function singleFilterFn() {
- for (const {
- key,
- matchValueIn,
- matchValueExists,
- } of singleFilter.allOf) {
+ for (const filter of singleFilter.allOf) {
+ if (
+ filter.hasOwnProperty('anyOf') ||
+ filter.hasOwnProperty('allOf')
+ ) {
+ throw new Error(
+ 'Nested filters are not supported in the legacy CommonDatabase',
+ );
+ }
+ const { key, matchValueIn, matchValueExists } = filter;
// NOTE(freben): This used to be a set of OUTER JOIN, which may seem to
// make a lot of sense. However, it had abysmal performance on sqlite
// when datasets grew large, so we're using IN instead.
diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts
index 082aa47df5..32d5fa843e 100644
--- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts
+++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts
@@ -23,6 +23,7 @@ import {
DbFinalEntitiesRow,
DbRefreshStateReferencesRow,
DbRefreshStateRow,
+ DbSearchRow,
} from '../database/tables';
import { NextEntitiesCatalog } from './NextEntitiesCatalog';
@@ -73,6 +74,52 @@ describe('NextEntitiesCatalog', () => {
}
}
+ async function addEntityToSearch(knex: Knex, entity: Entity) {
+ const id = uuid();
+ const entityRef = stringifyEntityRef(entity);
+ const entityJson = JSON.stringify(entity);
+
+ await knex('refresh_state').insert({
+ entity_id: id,
+ entity_ref: entityRef,
+ unprocessed_entity: entityJson,
+ errors: '[]',
+ next_update_at: '2031-01-01 23:00:00',
+ last_discovery_at: '2021-04-01 13:37:00',
+ });
+
+ await knex('final_entities').insert({
+ entity_id: id,
+ final_entity: entityJson,
+ hash: 'h',
+ stitch_ticket: '',
+ });
+
+ await insertSearchRow(knex, id, null, entity);
+ }
+
+ async function insertSearchRow(
+ knex: Knex,
+ id: string,
+ previousKey: string | null,
+ previousValue: Object,
+ ) {
+ return Promise.all(
+ Object.entries(previousValue).map(async ([key, value]) => {
+ const currentKey = `${previousKey ? `${previousKey}.` : ``}${key}`;
+ if (typeof value === 'object') {
+ await insertSearchRow(knex, id, currentKey, value);
+ } else {
+ await knex('search').insert({
+ entity_id: id,
+ key: currentKey,
+ value: value,
+ });
+ }
+ }),
+ );
+ }
+
describe('entityAncestry', () => {
it.each(databases.eachSupportedId())(
'should return the ancestry with one parent, %p',
@@ -209,4 +256,106 @@ describe('NextEntitiesCatalog', () => {
60_000,
);
});
+
+ describe('entities', () => {
+ it.each(databases.eachSupportedId())(
+ 'should return correct entity for simple filter',
+ async databaseId => {
+ const { knex } = await createDatabase(databaseId);
+ const entity1: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'one' },
+ spec: {},
+ };
+ const entity2: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'two' },
+ spec: {
+ test: 'test value',
+ },
+ };
+ await addEntityToSearch(knex, entity1);
+ await addEntityToSearch(knex, entity2);
+ const catalog = new NextEntitiesCatalog(knex);
+
+ const testFilter = {
+ key: 'spec.test',
+ matchValueExists: true,
+ };
+ const request = { filter: testFilter };
+ const { entities } = await catalog.entities(request);
+
+ expect(entities.length).toBe(1);
+ expect(entities[0]).toEqual(entity2);
+ },
+ );
+
+ it.each(databases.eachSupportedId())(
+ 'should return correct entity for nested filter',
+ async databaseId => {
+ const { knex } = await createDatabase(databaseId);
+ const entity1: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'one', org: 'a', desc: 'description' },
+ spec: {},
+ };
+ const entity2: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'two', org: 'b', desc: 'description' },
+ spec: {},
+ };
+ const entity3: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'three', org: 'b', color: 'red' },
+ spec: {},
+ };
+ const entity4: Entity = {
+ apiVersion: 'a',
+ kind: 'k',
+ metadata: { name: 'four', org: 'b', color: 'blue' },
+ spec: {},
+ };
+ await addEntityToSearch(knex, entity1);
+ await addEntityToSearch(knex, entity2);
+ await addEntityToSearch(knex, entity3);
+ await addEntityToSearch(knex, entity4);
+ const catalog = new NextEntitiesCatalog(knex);
+
+ const testFilter1 = {
+ key: 'metadata.org',
+ matchValueExists: true,
+ matchValueIn: ['b'],
+ };
+ const testFilter2 = {
+ key: 'metadata.desc',
+ matchValueExists: true,
+ };
+ const testFilter3 = {
+ key: 'metadata.color',
+ matchValueExists: true,
+ matchValueIn: ['blue'],
+ };
+ const request = {
+ filter: {
+ allOf: [
+ testFilter1,
+ {
+ anyOf: [testFilter2, testFilter3],
+ },
+ ],
+ },
+ };
+ const { entities } = await catalog.entities(request);
+
+ expect(entities.length).toBe(2);
+ expect(entities).toContainEqual(entity2);
+ expect(entities).toContainEqual(entity4);
+ },
+ );
+ });
});
diff --git a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts
index 0891be045d..841e57c921 100644
--- a/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts
+++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts
@@ -23,6 +23,8 @@ import {
EntitiesResponse,
EntityAncestryResponse,
EntityPagination,
+ EntityFilter,
+ EntitiesSearchFilter,
} from '../catalog/types';
import {
DbFinalEntitiesRow,
@@ -73,6 +75,90 @@ function stringifyPagination(input: { limit: number; offset: number }) {
return base64;
}
+function addCondition(
+ queryBuilder: Knex.QueryBuilder,
+ db: Knex,
+ { key, matchValueIn, matchValueExists }: EntitiesSearchFilter,
+) {
+ // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to
+ // make a lot of sense. However, it had abysmal performance on sqlite
+ // when datasets grew large, so we're using IN instead.
+ const matchQuery = db('search')
+ .select('entity_id')
+ .where(function keyFilter() {
+ this.andWhere({ key: key.toLowerCase() });
+ if (matchValueExists !== false && matchValueIn) {
+ if (matchValueIn.length === 1) {
+ this.andWhere({ value: matchValueIn[0].toLowerCase() });
+ } else if (matchValueIn.length > 1) {
+ this.andWhere(
+ 'value',
+ 'in',
+ matchValueIn.map(v => v.toLowerCase()),
+ );
+ }
+ }
+ });
+ // Explicitly evaluate matchValueExists as a boolean since it may be undefined
+ queryBuilder.andWhere(
+ 'entity_id',
+ matchValueExists === false ? 'not in' : 'in',
+ matchQuery,
+ );
+}
+
+function isEntitiesSearchFilter(
+ filter: EntitiesSearchFilter | EntityFilter,
+): filter is EntitiesSearchFilter {
+ return filter.hasOwnProperty('key');
+}
+
+function isAndEntityFilter(
+ filter: { allOf: EntityFilter[] } | EntityFilter,
+): filter is { allOf: EntityFilter[] } {
+ return filter.hasOwnProperty('allOf');
+}
+
+function isOrEntityFilter(
+ filter: { anyOf: EntityFilter[] } | EntityFilter,
+): filter is { anyOf: EntityFilter[] } {
+ return filter.hasOwnProperty('anyOf');
+}
+
+function parseFilter(
+ filter: EntityFilter,
+ query: Knex.QueryBuilder,
+ db: Knex,
+): Knex.QueryBuilder {
+ if (isEntitiesSearchFilter(filter)) {
+ return query.where(function filterFunction() {
+ addCondition(this, db, filter);
+ });
+ }
+
+ if (isOrEntityFilter(filter)) {
+ let cumulativeQuery = query;
+ for (const subFilter of filter.anyOf ?? []) {
+ cumulativeQuery = cumulativeQuery.orWhere(subQuery =>
+ parseFilter(subFilter, subQuery, db),
+ );
+ }
+ return cumulativeQuery;
+ }
+
+ if (isAndEntityFilter(filter)) {
+ let cumulativeQuery = query;
+ for (const subFilter of filter.allOf ?? []) {
+ cumulativeQuery = cumulativeQuery.andWhere(subQuery =>
+ parseFilter(subFilter, subQuery, db),
+ );
+ }
+ return cumulativeQuery;
+ }
+
+ return query;
+}
+
export class NextEntitiesCatalog implements EntitiesCatalog {
constructor(private readonly database: Knex) {}
@@ -80,41 +166,8 @@ export class NextEntitiesCatalog implements EntitiesCatalog {
const db = this.database;
let entitiesQuery = db('final_entities');
-
- for (const singleFilter of request?.filter?.anyOf ?? []) {
- entitiesQuery = entitiesQuery.orWhere(function singleFilterFn() {
- for (const {
- key,
- matchValueIn,
- matchValueExists,
- } of singleFilter.allOf) {
- // NOTE(freben): This used to be a set of OUTER JOIN, which may seem to
- // make a lot of sense. However, it had abysmal performance on sqlite
- // when datasets grew large, so we're using IN instead.
- const matchQuery = db('search')
- .select('entity_id')
- .where(function keyFilter() {
- this.andWhere({ key: key.toLowerCase() });
- if (matchValueExists !== false && matchValueIn) {
- if (matchValueIn.length === 1) {
- this.andWhere({ value: matchValueIn[0].toLowerCase() });
- } else if (matchValueIn.length > 1) {
- this.andWhere(
- 'value',
- 'in',
- matchValueIn.map(v => v.toLowerCase()),
- );
- }
- }
- });
- // Explicitly evaluate matchValueExists as a boolean since it may be undefined
- this.andWhere(
- 'entity_id',
- matchValueExists === false ? 'not in' : 'in',
- matchQuery,
- );
- }
- });
+ if (request?.filter) {
+ entitiesQuery = parseFilter(request.filter, entitiesQuery, db);
}
// TODO: move final_entities to use entity_ref
diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md
index bf8295a8b5..c4aa254226 100644
--- a/plugins/catalog-react/api-report.md
+++ b/plugins/catalog-react/api-report.md
@@ -15,6 +15,7 @@ import { Context } from 'react';
import { Entity } from '@backstage/catalog-model';
import { EntityName } from '@backstage/catalog-model';
import { IconButton } from '@material-ui/core';
+import { IdentityApi } from '@backstage/core-plugin-api';
import { LinkProps } from '@backstage/core-components';
import { Observable } from '@backstage/types';
import { PropsWithChildren } from 'react';
@@ -736,6 +737,17 @@ export function getEntitySourceLocation(
// @public
export function isOwnerOf(owner: Entity, owned: Entity): boolean;
+// @public
+export function loadCatalogOwnerRefs(
+ catalogApi: CatalogApi,
+ identityOwnerRefs: string[],
+): Promise;
+
+// @public
+export function loadIdentityOwnerRefs(
+ identityApi: IdentityApi,
+): Promise;
+
// Warning: (ae-missing-release-tag) "MockEntityListContextProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -823,8 +835,6 @@ export function useEntityListProvider<
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,
>(): EntityListContextProps;
-// Warning: (ae-missing-release-tag) "useEntityOwnership" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public
export function useEntityOwnership(): {
loading: boolean;
diff --git a/plugins/catalog-react/src/hooks/index.ts b/plugins/catalog-react/src/hooks/index.ts
index 38fc58222d..bbbca3a501 100644
--- a/plugins/catalog-react/src/hooks/index.ts
+++ b/plugins/catalog-react/src/hooks/index.ts
@@ -37,4 +37,8 @@ export { useOwnUser } from './useOwnUser';
export { useRelatedEntities } from './useRelatedEntities';
export { useStarredEntities } from './useStarredEntities';
export { useStarredEntity } from './useStarredEntity';
-export { useEntityOwnership } from './useEntityOwnership';
+export {
+ loadCatalogOwnerRefs,
+ useEntityOwnership,
+ loadIdentityOwnerRefs,
+} from './useEntityOwnership';
diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.ts b/plugins/catalog-react/src/hooks/useEntityOwnership.ts
index aee903603a..54e9e0ff99 100644
--- a/plugins/catalog-react/src/hooks/useEntityOwnership.ts
+++ b/plugins/catalog-react/src/hooks/useEntityOwnership.ts
@@ -49,9 +49,16 @@ function extendUserId(id: string): string {
}
}
-// Takes the relevant parts of the Backstage identity, and translates them into
-// a list of entity refs on string form that represent the user's ownership
-// connections.
+/**
+ * Takes the relevant parts of the Backstage identity, and translates them into
+ * a list of entity refs on string form that represent the user's ownership
+ * connections.
+ *
+ * @public
+ *
+ * @param identityApi - The IdentityApi implementation
+ * @returns IdentityOwner refs as a string array
+ */
export async function loadIdentityOwnerRefs(
identityApi: IdentityApi,
): Promise {
@@ -81,9 +88,17 @@ export async function loadIdentityOwnerRefs(
return result;
}
-// Takes the relevant parts of the User entity corresponding to the Backstage
-// identity, and translates them into a list of entity refs on string form that
-// represent the user's ownership connections.
+/**
+ * Takes the relevant parts of the User entity corresponding to the Backstage
+ * identity, and translates them into a list of entity refs on string form that
+ * represent the user's ownership connections.
+ *
+ * @public
+ *
+ * @param catalogApi - The Catalog API implementation
+ * @param identityOwnerRefs - List of identity owner refs as strings
+ * @returns OwnerRefs as a string array
+ */
export async function loadCatalogOwnerRefs(
catalogApi: CatalogApi,
identityOwnerRefs: string[],
@@ -113,6 +128,10 @@ export async function loadCatalogOwnerRefs(
* owner of a given entity. When the hook is initially mounted, the loading
* flag will be true and the results returned from the function will always be
* false.
+ *
+ * @public
+ *
+ * @returns a function that checks if the signed in user owns an entity
*/
export function useEntityOwnership(): {
loading: boolean;
diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json
index 2b09b4d99f..d01e12dff5 100644
--- a/plugins/code-coverage/package.json
+++ b/plugins/code-coverage/package.json
@@ -33,6 +33,7 @@
"@material-ui/lab": "4.0.0-alpha.57",
"@material-ui/styles": "^4.11.0",
"highlight.js": "^10.6.0",
+ "luxon": "^2.0.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router": "6.0.0-beta.0",
diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx
index 61dc7d7158..4291599098 100644
--- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx
+++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx
@@ -46,6 +46,8 @@ import { codeCoverageApiRef } from '../../api';
import { Progress, ResponseErrorPanel } from '@backstage/core-components';
import { useApi } from '@backstage/core-plugin-api';
+import { DateTime } from 'luxon';
+
type Coverage = 'line' | 'branch';
const useStyles = makeStyles(theme => ({
@@ -69,6 +71,13 @@ const getTrendIcon = (trend: number, classes: ClassNameMap) => {
}
};
+// convert timestamp to human friendly form
+function formatDateToHuman(timeStamp: string | number) {
+ return DateTime.fromMillis(Number(timeStamp)).toLocaleString(
+ DateTime.DATETIME_MED,
+ );
+}
+
export const CoverageHistoryChart = () => {
const { entity } = useEntity();
const codeCoverageApi = useApi(codeCoverageApiRef);
@@ -149,10 +158,10 @@ export const CoverageHistoryChart = () => {
margin={{ right: 48, top: 32 }}
>
-
+
-
+
{
title: 'Coverage',
type: 'numeric',
field: 'coverage',
- render: (row: CoverageTableRow) => `${row.coverage}%`,
+ render: (row: CoverageTableRow) => `${row.coverage.toFixed(2)}%`,
},
{
title: 'Missing lines',
diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json
index 87688e455f..2d5cabf725 100644
--- a/plugins/search-backend-module-elasticsearch/package.json
+++ b/plugins/search-backend-module-elasticsearch/package.json
@@ -22,7 +22,7 @@
"dependencies": {
"@backstage/config": "^0.1.8",
"@backstage/search-common": "^0.2.0",
- "@elastic/elasticsearch": "^7.13.0",
+ "@elastic/elasticsearch": "7.13.0",
"@acuris/aws-es-connection": "^2.2.0",
"aws-sdk": "^2.948.0",
"elastic-builder": "^2.16.0",
diff --git a/scripts/snyk-github-issue-sync.ts b/scripts/snyk-github-issue-sync.ts
new file mode 100644
index 0000000000..d7f64cf1ff
--- /dev/null
+++ b/scripts/snyk-github-issue-sync.ts
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+/* eslint-disable import/no-extraneous-dependencies */
+import { Octokit } from '@octokit/rest';
+import minimist from 'minimist';
+// Generated by GitHub workflow .github/workflows/snyk-github-issue-creator
+import synkJsonOutput from '../snyk.json';
+
+type Vulnerability = {
+ description: string;
+ packages: {
+ name: string;
+ target: string;
+ }[];
+ snykId: string;
+};
+
+const argv = minimist(process.argv.slice(2));
+
+const GH_OWNER = 'backstage';
+const GH_REPO = 'backstage';
+const SNYK_GH_LABEL = 'snyk-vulnerability';
+const SNYK_ID_REGEX = /\[([A-Z0-9-:]+)]/i;
+
+const isDryRun = 'dryrun' in argv;
+
+if (!process.env.GITHUB_TOKEN) {
+ console.error('GITHUB_TOKEN is not set. Please provide a Github token');
+ process.exit(1);
+}
+
+const octokit = new Octokit({
+ auth: process.env.GITHUB_TOKEN,
+});
+
+if (isDryRun) {
+ console.log(
+ '⚠️ Running in dryrun mode, no issues will be updated on Github ⚠️',
+ );
+}
+
+const fetchSnykGithubIssueMap = async (): Promise> => {
+ const snykGithubIssueMap: Record = {};
+
+ const iterator = octokit.paginate.iterator(octokit.rest.issues.listForRepo, {
+ owner: GH_OWNER,
+ repo: GH_REPO,
+ per_page: 100,
+ state: 'open',
+ labels: SNYK_GH_LABEL,
+ });
+
+ for await (const { data: issues } of iterator) {
+ for (const issue of issues) {
+ // Gets the Vulnerability ID from square braces
+ const match = SNYK_ID_REGEX.exec(issue.title);
+
+ if (match && match[1]) {
+ snykGithubIssueMap[match[1]] = issue.number;
+ } else {
+ console.log(`Unmatched Snyk ID for ${issue.title}`);
+ }
+ }
+ }
+
+ return snykGithubIssueMap;
+};
+
+const generateIssueBody = (vulnerability: Vulnerability) => `
+## Affecting Packages/Plugins
+
+${Array.from(vulnerability.packages).map(
+ ({ name, target }) => `* [${name}](${target})\n`,
+)}
+
+${vulnerability.description}
+`;
+
+const createGithubIssue = async (vulnerability: Vulnerability) => {
+ console.log(
+ `Create Github Issue for Snyk Vulnerability ${vulnerability.snykId}`,
+ );
+
+ vulnerability.packages.forEach(({ name, target }) => {
+ console.log(`- ${name} [${target}]`);
+ });
+
+ if (!isDryRun) {
+ await octokit.issues.create({
+ owner: GH_OWNER,
+ repo: GH_REPO,
+ title: `Snyk vulnerability [${vulnerability.snykId}]`,
+ labels: [SNYK_GH_LABEL, 'help wanted'],
+ body: generateIssueBody(vulnerability),
+ });
+ }
+};
+
+const updateGithubIssue = async (
+ githubIssueId: number,
+ vulnerability: Vulnerability,
+) => {
+ console.log(
+ `Update Github Issue #${githubIssueId} for Snky Vulnerability ${vulnerability.snykId}`,
+ );
+
+ if (!isDryRun) {
+ await octokit.issues.update({
+ owner: GH_OWNER,
+ repo: GH_REPO,
+ issue_number: githubIssueId,
+ body: generateIssueBody(vulnerability),
+ });
+ }
+};
+
+const closeGithubIssue = async (githubIssueId: number) => {
+ console.log(`Closing Github Issue #${githubIssueId}`);
+
+ if (!isDryRun) {
+ await octokit.issues.update({
+ owner: GH_OWNER,
+ repo: GH_REPO,
+ issue_number: githubIssueId,
+ state: 'closed',
+ });
+ }
+};
+
+async function main() {
+ const snykGithubIssueMap = await fetchSnykGithubIssueMap();
+ const vulnerabilityStore: Record = {};
+
+ // Group the Snyk vulnerabilities, and link back to the affecting packages.
+ synkJsonOutput.forEach(
+ ({ projectName, displayTargetFile, vulnerabilities }) => {
+ vulnerabilities.forEach(
+ ({ id, description }: { id: string; description: string }) => {
+ if (id !== undefined && description !== undefined) {
+ if (vulnerabilityStore[id]) {
+ if (
+ !vulnerabilityStore[id].packages.some(
+ ({ name }) => name === projectName,
+ )
+ ) {
+ vulnerabilityStore[id].packages.push({
+ name: projectName,
+ target: displayTargetFile,
+ });
+ }
+ } else {
+ vulnerabilityStore[id] = {
+ description,
+ snykId: id,
+ packages: [
+ {
+ name: projectName,
+ target: displayTargetFile,
+ },
+ ],
+ };
+ }
+ }
+ },
+ );
+ },
+ );
+
+ for (const [id, vulnerability] of Object.entries(vulnerabilityStore)) {
+ if (snykGithubIssueMap[id]) {
+ await updateGithubIssue(snykGithubIssueMap[id], vulnerability);
+ } else {
+ await createGithubIssue(vulnerability);
+ }
+ }
+
+ for (const [snykId, githubIssueId] of Object.entries(snykGithubIssueMap)) {
+ if (!vulnerabilityStore[snykId]) {
+ await closeGithubIssue(githubIssueId);
+ }
+ }
+}
+
+main().catch(error => {
+ console.error(error.stack);
+ process.exit(1);
+});
diff --git a/yarn.lock b/yarn.lock
index 28e400827b..b5786626dd 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2712,7 +2712,7 @@
find-my-way "^2.2.2"
into-stream "^5.1.1"
-"@elastic/elasticsearch@^7.13.0":
+"@elastic/elasticsearch@7.13.0":
version "7.13.0"
resolved "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.13.0.tgz#6dcf511dfa91187e22c81e54f41f4bd0fd96b4d6"
integrity sha512-WgwLWo2p9P2tdqzBGX9fHeG8p5IOTXprXNTECQG2mJ7z9n93N5AFBJpEw4d35tWWeCWi9jI13A2wzQZH7XZ/xw==
@@ -2968,16 +2968,14 @@
stream-events "^1.0.1"
xdg-basedir "^4.0.0"
-"@graphiql/toolkit@^0.2.0":
- version "0.2.2"
- resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.2.2.tgz#193d570afcf686c9ee61c92054c1782b9f3c1255"
- integrity sha512-kDgYhqnS4p4LqSo1KvLd3tbX8Hhdj0ZrgQuGsosjjEnahiPYmmylxUL1p9lj6348OsypcTlCncGpEjeb9S3TiQ==
+"@graphiql/toolkit@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.3.2.tgz#551753436ada2bc27ea870b7668e5199a958ccfb"
+ integrity sha512-IweIT9VC8uDovg7kuCO9YqZcnIuWU8IGzrpUisXv6CUNK2Ed1ke8yERDTMmF/rjvLd2DeVZwM8iEOjEs4sUJQw==
dependencies:
- "@n1ru4l/push-pull-async-iterable-iterator" "^2.1.4"
- graphql-ws "^4.3.2"
+ "@n1ru4l/push-pull-async-iterable-iterator" "^3.0.0"
+ graphql-ws "^4.9.0"
meros "^1.1.4"
- optionalDependencies:
- subscriptions-transport-ws "^0.9.18"
"@graphql-codegen/cli@^1.21.3":
version "1.21.6"
@@ -4635,10 +4633,10 @@
outvariant "^1.2.0"
strict-event-emitter "^0.2.0"
-"@n1ru4l/push-pull-async-iterable-iterator@^2.1.4":
- version "2.1.4"
- resolved "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-2.1.4.tgz#a90225474352f9f159bff979905f707b9c6bcf04"
- integrity sha512-qLIvoOUJ+zritv+BlzcBMePKNjKQzH9Rb2i9W98YXxf/M62Lye8qH0peyiU8yJ1tL0kfulWi31BoK10E6BKJeA==
+"@n1ru4l/push-pull-async-iterable-iterator@^3.0.0":
+ version "3.1.0"
+ resolved "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.1.0.tgz#be450c97d1c7cd6af1a992d53232704454345df9"
+ integrity sha512-K4scWxGhdQM0masHHy4gIQs2iGiLEXCrXttumknyPJqtdl4J179BjpibWSSQ1fxKdCcHgIlCTKXJU6cMM6D6Wg==
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
@@ -4893,6 +4891,19 @@
before-after-hook "^2.1.0"
universal-user-agent "^6.0.0"
+"@octokit/core@^3.5.1":
+ version "3.5.1"
+ resolved "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b"
+ integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==
+ dependencies:
+ "@octokit/auth-token" "^2.4.4"
+ "@octokit/graphql" "^4.5.8"
+ "@octokit/request" "^5.6.0"
+ "@octokit/request-error" "^2.0.5"
+ "@octokit/types" "^6.0.3"
+ before-after-hook "^2.2.0"
+ universal-user-agent "^6.0.0"
+
"@octokit/endpoint@^6.0.1":
version "6.0.3"
resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.3.tgz#dd09b599662d7e1b66374a177ab620d8cdf73487"
@@ -4927,6 +4938,11 @@
"@octokit/types" "^6.12.2"
btoa-lite "^1.0.0"
+"@octokit/openapi-types@^11.2.0":
+ version "11.2.0"
+ resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6"
+ integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==
+
"@octokit/openapi-types@^7.3.2":
version "7.3.2"
resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-7.3.2.tgz#065ce49b338043ec7f741316ce06afd4d459d944"
@@ -4937,6 +4953,13 @@
resolved "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437"
integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==
+"@octokit/plugin-paginate-rest@^2.16.8":
+ version "2.17.0"
+ resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7"
+ integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==
+ dependencies:
+ "@octokit/types" "^6.34.0"
+
"@octokit/plugin-paginate-rest@^2.6.2":
version "2.7.0"
resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.7.0.tgz#6bb7b043c246e0654119a6ec4e72a172c9e2c7f3"
@@ -4949,6 +4972,11 @@
resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz#394d59ec734cd2f122431fbaf05099861ece3c44"
integrity sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg==
+"@octokit/plugin-request-log@^1.0.4":
+ version "1.0.4"
+ resolved "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85"
+ integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
+
"@octokit/plugin-rest-endpoint-methods@5.3.1":
version "5.3.1"
resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.3.1.tgz#deddce769b4ec3179170709ab42e4e9e6195aaa9"
@@ -4957,6 +4985,14 @@
"@octokit/types" "^6.16.2"
deprecation "^2.3.1"
+"@octokit/plugin-rest-endpoint-methods@^5.12.0":
+ version "5.13.0"
+ resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba"
+ integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==
+ dependencies:
+ "@octokit/types" "^6.34.0"
+ deprecation "^2.3.1"
+
"@octokit/request-error@^2.0.0", "@octokit/request-error@^2.0.2", "@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0":
version "2.1.0"
resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677"
@@ -4988,6 +5024,16 @@
"@octokit/plugin-request-log" "^1.0.2"
"@octokit/plugin-rest-endpoint-methods" "5.3.1"
+"@octokit/rest@^18.12.0":
+ version "18.12.0"
+ resolved "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881"
+ integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==
+ dependencies:
+ "@octokit/core" "^3.5.1"
+ "@octokit/plugin-paginate-rest" "^2.16.8"
+ "@octokit/plugin-request-log" "^1.0.4"
+ "@octokit/plugin-rest-endpoint-methods" "^5.12.0"
+
"@octokit/types@^5.0.0", "@octokit/types@^5.0.1":
version "5.5.0"
resolved "https://registry.npmjs.org/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b"
@@ -5002,6 +5048,13 @@
dependencies:
"@octokit/openapi-types" "^7.3.2"
+"@octokit/types@^6.34.0":
+ version "6.34.0"
+ resolved "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218"
+ integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==
+ dependencies:
+ "@octokit/openapi-types" "^11.2.0"
+
"@octokit/webhooks-methods@^2.0.0":
version "2.0.0"
resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db"
@@ -9898,6 +9951,11 @@ before-after-hook@^2.1.0:
resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==
+before-after-hook@^2.2.0:
+ version "2.2.2"
+ resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e"
+ integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
+
better-opn@^2.1.1:
version "2.1.1"
resolved "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz#94a55b4695dc79288f31d7d0e5f658320759f7c6"
@@ -11076,18 +11134,18 @@ code-point-at@^1.0.0:
resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-codemirror-graphql@^1.0.0:
- version "1.0.0"
- resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-1.0.0.tgz#ba8db60dc42b87768d643b3d19bf088f43dc5380"
- integrity sha512-6LnSeRldL7psIBfjDr4xXKxCqPVYfQE4Yj04p2VpIyAIpc4MVE4VOjzvILgnmAW8X93ou5/s5gQXvB4huDwTUQ==
+codemirror-graphql@^1.0.3:
+ version "1.1.0"
+ resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-1.1.0.tgz#dd22ddf7761efa9131fa99a70a4a85fe653484e5"
+ integrity sha512-bp2XUg7epL07kJcylM8VCISK6X+rFsHL2lUkPQAw2v721MVhn+80FgjMP8tiZCOfJgHn1+JgsA71L5nOHWgUdA==
dependencies:
- graphql-language-service-interface "^2.8.2"
- graphql-language-service-parser "^1.9.0"
+ graphql-language-service-interface "^2.9.0"
+ graphql-language-service-parser "^1.10.0"
-codemirror@^5.54.0:
- version "5.59.4"
- resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.59.4.tgz#bfc11c8ce32b04818e8d661bbd790a94f4b3a6f3"
- integrity sha512-achw5JBgx8QPcACDDn+EUUXmCYzx/zxEtOGXyjvLEvYY8GleUrnfm5D+Zb+UjShHggXKDT9AXrbkBZX6a0YSQg==
+codemirror@^5.58.2:
+ version "5.63.3"
+ resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.63.3.tgz#97042a242027fe0c87c09b36bc01931d37b76527"
+ integrity sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw==
codeowners-utils@^1.0.2:
version "1.0.2"
@@ -13358,7 +13416,12 @@ entities@^1.1.1, entities@^1.1.2:
resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
-entities@^2.0.0, entities@~2.0.0:
+entities@^2.0.0, entities@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
+ integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
+
+entities@~2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4"
integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==
@@ -14372,11 +14435,6 @@ fecha@^4.2.0:
resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41"
integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==
-fetch-blob@2.1.2:
- version "2.1.2"
- resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz#a7805db1361bd44c1ef62bb57fb5fe8ea173ef3c"
- integrity sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==
-
fetch-readablestream@^0.2.0:
version "0.2.0"
resolved "https://registry.npmjs.org/fetch-readablestream/-/fetch-readablestream-0.2.0.tgz#eaa6d1a76b12de2d4731a343393c6ccdcfe2c795"
@@ -15486,18 +15544,19 @@ grapheme-splitter@^1.0.4:
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
graphiql@^1.0.0-alpha.10:
- version "1.4.2"
- resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.4.2.tgz#a1dc1a4d8d35f60c90d6d8a9eb62a99756e9fd9b"
- integrity sha512-TQDuuU/ZqTWV1yQDpVEiKskg0IYA+Wck37DYrrFzLlpgZWRbWiyab1PyHKiRep7J540CgScBg6C/gGCymKyO3g==
+ version "1.4.7"
+ resolved "https://registry.npmjs.org/graphiql/-/graphiql-1.4.7.tgz#6a35acf0786d7518fbb986b75bf0a3d752c19c1a"
+ integrity sha512-oHsBTzdWTbRJhqazbjrC6wY7YInViErAeXLqetCxdFFu2Zk5FV3V3rs7KPrCyr7kM6lW0nfXMzIfKuIgxAqx7g==
dependencies:
- "@graphiql/toolkit" "^0.2.0"
- codemirror "^5.54.0"
- codemirror-graphql "^1.0.0"
+ "@graphiql/toolkit" "^0.3.2"
+ codemirror "^5.58.2"
+ codemirror-graphql "^1.0.3"
copy-to-clipboard "^3.2.0"
dset "^3.1.0"
entities "^2.0.0"
- graphql-language-service "^3.1.2"
- markdown-it "^10.0.0"
+ escape-html "^1.0.3"
+ graphql-language-service "^3.1.6"
+ markdown-it "^12.2.0"
graphlib@^2.1.8:
version "2.1.8"
@@ -15532,7 +15591,7 @@ graphql-extensions@^0.15.0:
apollo-server-env "^3.1.0"
apollo-server-types "^0.9.0"
-graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.8.2:
+graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.9.0:
version "2.8.2"
resolved "https://registry.npmjs.org/graphql-language-service-interface/-/graphql-language-service-interface-2.8.2.tgz#b3bb2aef7eaf0dff0b4ea419fa412c5f66fa268b"
integrity sha512-otbOQmhgkAJU1QJgQkMztNku6SbJLu/uodoFOYOOtJsizTjrMs93vkYaHCcYnLA3oi1Goj27XcHjMnRCYQOZXQ==
@@ -15542,7 +15601,7 @@ graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.
graphql-language-service-utils "^2.5.1"
vscode-languageserver-types "^3.15.1"
-graphql-language-service-parser@1.9.0, graphql-language-service-parser@^1.9.0:
+graphql-language-service-parser@1.9.0, graphql-language-service-parser@^1.10.0, graphql-language-service-parser@^1.9.0:
version "1.9.0"
resolved "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.0.tgz#79af21294119a0a7e81b6b994a1af36833bab724"
integrity sha512-B5xPZLbBmIp0kHvpY1Z35I5DtPoDK9wGxQVRDIzcBaiIvAmlTrDvjo3bu7vKREdjFbYKvWNgrEWENuprMbF17Q==
@@ -15554,6 +15613,11 @@ graphql-language-service-types@^1.8.0:
resolved "https://registry.npmjs.org/graphql-language-service-types/-/graphql-language-service-types-1.8.1.tgz#963810010924f2b5eaea415d5b8eb0b7d42c479b"
integrity sha512-IpYS0mEHEmRsFlq+loWCpSYYYizAID7Alri6GoFN1QqUdux+8rp1Tkp2NGsGDpDmm3Dbz5ojmJWzNWQGpuwveA==
+graphql-language-service-types@^1.8.2:
+ version "1.8.2"
+ resolved "https://registry.npmjs.org/graphql-language-service-types/-/graphql-language-service-types-1.8.2.tgz#50ae56f69cc24fcfc3daa129b68b0eb9421e8578"
+ integrity sha512-Sj07RHnMwAhEvAt7Jdt1l/x56ZpoNh+V6g+T58CF6GiYqI5l4vXqqRB4d4xHDcNQX98GpJfnf3o8BqPgP3C5Sw==
+
graphql-language-service-utils@^2.5.1:
version "2.5.1"
resolved "https://registry.npmjs.org/graphql-language-service-utils/-/graphql-language-service-utils-2.5.1.tgz#832ad4b0a9da03fdded756932c27e057ccf71302"
@@ -15562,13 +15626,23 @@ graphql-language-service-utils@^2.5.1:
graphql-language-service-types "^1.8.0"
nullthrows "^1.0.0"
-graphql-language-service@^3.1.2:
- version "3.1.2"
- resolved "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-3.1.2.tgz#6f50d5d824ea09c402cb02902b10e54b9da899d5"
- integrity sha512-OiOH8mVE+uotrl3jGA2Pgt9k7rrI8lgw/8p+Cf6nwyEHbmIZj37vX9KoOWgpdFhuQlw824nNxWHSbz6k90xjWQ==
+graphql-language-service-utils@^2.5.3:
+ version "2.5.3"
+ resolved "https://registry.npmjs.org/graphql-language-service-utils/-/graphql-language-service-utils-2.5.3.tgz#185f4f65cf8c010871eb9405452a3a0bfdf88748"
+ integrity sha512-ydevEZ0AgzEKQF3hiCbLXuS0o7189Ww/T30WtCKCLaRHDYk9Yyb2PZWdhSTWLxYZTaX2TccV6NtFWvzIC7UP3g==
dependencies:
- graphql-language-service-interface "^2.8.2"
graphql-language-service-types "^1.8.0"
+ nullthrows "^1.0.0"
+
+graphql-language-service@^3.1.6:
+ version "3.2.0"
+ resolved "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-3.2.0.tgz#e0eb6d5dea2cab92549a253d7a6b4fa0cce178b7"
+ integrity sha512-xM5Ua5p7ttG/oEaDy2zk35FP2O2I9qD2N0DOrjCDUVDRC06FNDG+/CvF4qX9+i8DWOI65xch5vAhSQEfS2jFsA==
+ dependencies:
+ graphql-language-service-interface "^2.9.0"
+ graphql-language-service-parser "^1.10.0"
+ graphql-language-service-types "^1.8.2"
+ graphql-language-service-utils "^2.5.3"
graphql-request@^3.3.0:
version "3.4.0"
@@ -15623,16 +15697,16 @@ graphql-type-json@^0.3.2:
resolved "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz#f53a851dbfe07bd1c8157d24150064baab41e115"
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
-graphql-ws@^4.3.2:
- version "4.9.0"
- resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-4.9.0.tgz#5cfd8bb490b35e86583d8322f5d5d099c26e365c"
- integrity sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag==
-
graphql-ws@^4.4.1:
version "4.7.0"
resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-4.7.0.tgz#b323fbf35a3736eed85dac24c0054d6d10c93e62"
integrity sha512-Md8SsmC9ZlsogFPd3Ot8HbIAAqsHh8Xoq7j4AmcIat1Bh6k91tjVyQvA0Au1/BolXSYq+RDvib6rATU2Hcf1Xw==
+graphql-ws@^4.9.0:
+ version "4.9.0"
+ resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-4.9.0.tgz#5cfd8bb490b35e86583d8322f5d5d099c26e365c"
+ integrity sha512-sHkK9+lUm20/BGawNEWNtVAeJzhZeBg21VmvmLoT5NdGVeZWv5PdIhkcayQIAgjSyyQ17WMKmbDijIPG2On+Ag==
+
graphql@15.5.0:
version "15.5.0"
resolved "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
@@ -18761,13 +18835,6 @@ lines-and-columns@^1.1.6:
resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
-linkify-it@^2.0.0:
- version "2.2.0"
- resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf"
- integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==
- dependencies:
- uc.micro "^1.0.1"
-
linkify-it@^3.0.1:
version "3.0.2"
resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
@@ -19463,17 +19530,6 @@ markdown-escapes@^1.0.0:
resolved "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
-markdown-it@^10.0.0:
- version "10.0.0"
- resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc"
- integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==
- dependencies:
- argparse "^1.0.7"
- entities "~2.0.0"
- linkify-it "^2.0.0"
- mdurl "^1.0.1"
- uc.micro "^1.0.5"
-
markdown-it@^11.0.1:
version "11.0.1"
resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-11.0.1.tgz#b54f15ec2a2193efa66dda1eb4173baea08993d6"
@@ -19485,6 +19541,17 @@ markdown-it@^11.0.1:
mdurl "^1.0.1"
uc.micro "^1.0.5"
+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==
+ dependencies:
+ argparse "^2.0.1"
+ entities "~2.1.0"
+ linkify-it "^3.0.1"
+ mdurl "^1.0.1"
+ uc.micro "^1.0.5"
+
markdown-table@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b"
@@ -22056,9 +22123,9 @@ passport-oauth2@1.2.0:
uid2 "0.0.x"
passport-oauth2@1.x.x, passport-oauth2@^1.1.2, passport-oauth2@^1.4.0, passport-oauth2@^1.5.0:
- version "1.6.0"
- resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.0.tgz#5f599735e0ea40ea3027643785f81a3a9b4feb50"
- integrity sha512-emXPLqLcVEcLFR/QvQXZcwLmfK8e9CqvMgmOFJxcNT3okSFMtUbRRKpY20x5euD+01uHsjjCa07DYboEeLXYiw==
+ version "1.6.1"
+ resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b"
+ integrity sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ==
dependencies:
base64url "3.x.x"
oauth "0.9.x"
@@ -28523,11 +28590,6 @@ webidl-conversions@^3.0.0:
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
-webidl-conversions@^4.0.2:
- version "4.0.2"
- resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
- integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
-
webidl-conversions@^5.0.0:
version "5.0.0"
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
@@ -28751,24 +28813,6 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
-whatwg-url@^6.4.1:
- version "6.5.0"
- resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
- integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==
- dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^1.0.1"
- webidl-conversions "^4.0.2"
-
-whatwg-url@^7.0.0:
- version "7.1.0"
- resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
- integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
- dependencies:
- lodash.sortby "^4.7.0"
- tr46 "^1.0.1"
- webidl-conversions "^4.0.2"
-
whatwg-url@^8.0.0, whatwg-url@^8.4.0:
version "8.4.0"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz#50fb9615b05469591d2b2bd6dfaed2942ed72837"