From 07dda0b746a9dd16ea5921fb72f1ef0312d0a999 Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Wed, 31 Aug 2022 14:06:00 +0200 Subject: [PATCH 01/95] Add optional value to hasAnnotation. Signed-off-by: Axel Hecht --- .changeset/famous-rats-heal.md | 5 ++ plugins/catalog-backend/api-report.md | 4 +- .../permissions/rules/hasAnnotation.test.ts | 62 +++++++++++++++++++ .../src/permissions/rules/hasAnnotation.ts | 21 +++++-- 4 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 .changeset/famous-rats-heal.md diff --git a/.changeset/famous-rats-heal.md b/.changeset/famous-rats-heal.md new file mode 100644 index 0000000000..e233070849 --- /dev/null +++ b/.changeset/famous-rats-heal.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Add optional value to hasAnnotation permission rule diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 0460fbc5e9..8a2b0fc9cc 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -177,7 +177,7 @@ export const catalogConditions: Conditions<{ Entity, EntitiesSearchFilter, 'catalog-entity', - [annotation: string] + [annotation: string, value?: string | undefined] >; hasLabel: PermissionRule< Entity, @@ -448,7 +448,7 @@ export const permissionRules: { Entity, EntitiesSearchFilter, 'catalog-entity', - [annotation: string] + [annotation: string, value?: string | undefined] >; hasLabel: PermissionRule< Entity, diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts index 1596270907..609114be3d 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.test.ts @@ -49,6 +49,19 @@ describe('hasAnnotation permission rule', () => { 'backstage.io/test-annotation', ), ).toEqual(false); + expect( + hasAnnotation.apply( + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'test-component', + }, + }, + 'backstage.io/test-annotation', + 'some value', + ), + ).toEqual(false); }); it('returns true when specified annotation is present', () => { @@ -69,6 +82,46 @@ describe('hasAnnotation permission rule', () => { ), ).toEqual(true); }); + + it('returns false when specified annotation has different than expected value', () => { + 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', + 'baz', + ), + ).toEqual(false); + }); + + it('returns true when specified annotation has expected value', () => { + 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', + 'bar', + ), + ).toEqual(true); + }); }); describe('toQuery', () => { @@ -78,4 +131,13 @@ describe('hasAnnotation permission rule', () => { }); }); }); + + it('returns an appropriate catalog-backend filter with values', () => { + expect( + hasAnnotation.toQuery('backstage.io/test-annotation', 'foo'), + ).toEqual({ + key: 'metadata.annotations.backstage.io/test-annotation', + values: ['foo'], + }); + }); }); diff --git a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts index 68ca65418d..22dbd307a6 100644 --- a/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts +++ b/plugins/catalog-backend/src/permissions/rules/hasAnnotation.ts @@ -22,6 +22,8 @@ import { createCatalogPermissionRule } from './util'; * A catalog {@link @backstage/plugin-permission-node#PermissionRule} which * filters for the presence of an annotation on a given entity. * + * If a value is given, it filters for the annotation value, too. + * * @alpha */ export const hasAnnotation = createCatalogPermissionRule({ @@ -29,9 +31,18 @@ export const hasAnnotation = createCatalogPermissionRule({ description: 'Allow entities which are annotated with the specified annotation', resourceType: RESOURCE_TYPE_CATALOG_ENTITY, - apply: (resource: Entity, annotation: string) => - !!resource.metadata.annotations?.hasOwnProperty(annotation), - toQuery: (annotation: string) => ({ - key: `metadata.annotations.${annotation}`, - }), + apply: (resource: Entity, annotation: string, value?: string) => + !!resource.metadata.annotations?.hasOwnProperty(annotation) && + (value === undefined + ? true + : resource.metadata.annotations?.[annotation] === value), + toQuery: (annotation: string, value?: string) => + value === undefined + ? { + key: `metadata.annotations.${annotation}`, + } + : { + key: `metadata.annotations.${annotation}`, + values: [value], + }, }); From 6253418cb3b6c7154b0d2ba51a1a62e89c7a528a Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Thu, 8 Sep 2022 08:52:04 +0200 Subject: [PATCH 02/95] Provide information about the user into scaffolder template action's context Signed-off-by: bnechyporenko --- .../lib/resolvers/CatalogAuthResolverContext.ts | 2 +- .../src/scaffolder/actions/types.ts | 17 ++++++++++++++++- .../scaffolder/tasks/NunjucksWorkflowRunner.ts | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts index cbc2439563..c62c0737d8 100644 --- a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts +++ b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts @@ -27,7 +27,7 @@ import { ConflictError, InputError, NotFoundError } from '@backstage/errors'; import { Logger } from 'winston'; import { TokenIssuer, TokenParams } from '../../identity/types'; import { AuthResolverContext } from '../../providers'; -import { AuthResolverCatalogUserQuery } from '../../providers/types'; +import { AuthResolverCatalogUserQuery } from '../../providers'; import { CatalogIdentityClient } from '../catalog'; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts index ff15300b4a..666f7a0d50 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts @@ -18,8 +18,9 @@ import { Logger } from 'winston'; import { Writable } from 'stream'; import { JsonValue, JsonObject } from '@backstage/types'; import { Schema } from 'jsonschema'; -import { TaskSecrets } from '../tasks/types'; +import { TaskSecrets } from '../tasks'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; +import { UserEntity } from '@backstage/catalog-model'; /** * ActionContext is passed into scaffolder actions. @@ -45,6 +46,20 @@ export type ActionContext = { * This will only ever be true if the actions as marked as supporting dry-runs. */ isDryRun?: boolean; + + /** + * The user which triggered the action. + */ + user?: { + /** + * The decorated entity from the Catalog + */ + entity?: UserEntity; + /** + * An entity ref for the author of the task + */ + ref?: string; + }; }; /** @public */ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 97e37fd3eb..6e35f7c69b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -300,6 +300,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { stepOutput[name] = value; }, templateInfo: task.spec.templateInfo, + user: task.spec.user, }); // Remove all temporary directories that were created when executing the action From de8ee4afe301b13da181aef2ae0acc04e140412d Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Thu, 8 Sep 2022 08:57:42 +0200 Subject: [PATCH 03/95] Provide information about the user into scaffolder template action's context Signed-off-by: bnechyporenko --- .changeset/hungry-llamas-tie.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/hungry-llamas-tie.md diff --git a/.changeset/hungry-llamas-tie.md b/.changeset/hungry-llamas-tie.md new file mode 100644 index 0000000000..c4848b50ef --- /dev/null +++ b/.changeset/hungry-llamas-tie.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Provide information about the user into scaffolder template action's context From 820628b17f844ec7dbda7c5919f28a900deb3585 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Thu, 8 Sep 2022 09:21:25 +0200 Subject: [PATCH 04/95] Updated api-report.md Signed-off-by: bnechyporenko --- plugins/scaffolder-backend/api-report.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 44bf45061b..0d5fbcb31f 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -31,6 +31,7 @@ import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskSpecV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateInfo } from '@backstage/plugin-scaffolder-common'; import { UrlReader } from '@backstage/backend-common'; +import { UserEntity } from '@backstage/catalog-model'; import { Writable } from 'stream'; // @public @@ -44,6 +45,10 @@ export type ActionContext = { createTemporaryDirectory(): Promise; templateInfo?: TemplateInfo; isDryRun?: boolean; + user?: { + entity?: UserEntity; + ref?: string; + }; }; // @public From 63b0626c9d3be0e33408a144b6eb27afea76580f Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Thu, 8 Sep 2022 11:00:55 +0200 Subject: [PATCH 05/95] Added a unit test Signed-off-by: bnechyporenko --- .../tasks/NunjucksWorkflowRunner.test.ts | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 3627d83aa7..5af26bfea3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -66,7 +66,7 @@ describe('DefaultWorkflowRunner', () => { }); beforeEach(() => { - winston.format.simple(); // put logform the require cache before mocking fs + winston.format.simple(); // put logform the required cache before mocking fs mockFs({ '/tmp': mockFs.directory(), ...realFiles, @@ -169,6 +169,21 @@ describe('DefaultWorkflowRunner', () => { it('should pass metadata through', async () => { const entityRef = `template:default/templateName`; + + const userEntity: UserEntity = { + apiVersion: 'backstage.io/v1beta1', + kind: 'User', + metadata: { + name: 'user', + }, + spec: { + profile: { + displayName: 'Bogdan Nechyporenko', + email: 'bnechyporenko@company.com', + }, + }, + }; + const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', parameters: {}, @@ -182,6 +197,9 @@ describe('DefaultWorkflowRunner', () => { }, ], templateInfo: { entityRef }, + user: { + entity: userEntity, + }, }); await runner.execute(task); @@ -189,6 +207,10 @@ describe('DefaultWorkflowRunner', () => { expect(fakeActionHandler.mock.calls[0][0].templateInfo).toEqual({ entityRef, }); + + expect(fakeActionHandler.mock.calls[0][0].user).toEqual({ + entity: userEntity, + }); }); it('should pass token through', async () => { From 19ac96e4c2987c31af0c97ecbe01cdca5c0288dc Mon Sep 17 00:00:00 2001 From: David Zemon Date: Thu, 8 Sep 2022 11:36:49 -0500 Subject: [PATCH 06/95] feat: Allow passing additional JWT claims to `TokenIssuer` Signed-off-by: David Zemon --- plugins/auth-backend/src/identity/TokenFactory.test.ts | 8 +++++++- plugins/auth-backend/src/identity/TokenFactory.ts | 5 ++--- plugins/auth-backend/src/identity/types.ts | 10 ++++++++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/plugins/auth-backend/src/identity/TokenFactory.test.ts b/plugins/auth-backend/src/identity/TokenFactory.test.ts index 9a163b3ff5..4f6df89210 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.test.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.test.ts @@ -48,7 +48,12 @@ describe('TokenFactory', () => { await expect(factory.listPublicKeys()).resolves.toEqual({ keys: [] }); const token = await factory.issueToken({ - claims: { sub: entityRef, ent: [entityRef] }, + claims: { + sub: entityRef, + ent: [entityRef], + 'x-fancy-claim': 'my special claim', + aud: 'this value will be overridden', + }, }); const { keys } = await factory.listPublicKeys(); @@ -60,6 +65,7 @@ describe('TokenFactory', () => { aud: 'backstage', sub: entityRef, ent: [entityRef], + 'x-fancy-claim': 'my special claim', iat: expect.any(Number), exp: expect.any(Number), }); diff --git a/plugins/auth-backend/src/identity/TokenFactory.ts b/plugins/auth-backend/src/identity/TokenFactory.ts index 44cfebfb71..f80b79b6bc 100644 --- a/plugins/auth-backend/src/identity/TokenFactory.ts +++ b/plugins/auth-backend/src/identity/TokenFactory.ts @@ -77,8 +77,7 @@ export class TokenFactory implements TokenIssuer { const key = await this.getKey(); const iss = this.issuer; - const sub = params.claims.sub; - const ent = params.claims.ent; + const { sub, ent, ...additionalClaims } = params.claims; const aud = 'backstage'; const iat = Math.floor(Date.now() / MS_IN_S); const exp = iat + this.keyDurationSeconds; @@ -98,7 +97,7 @@ export class TokenFactory implements TokenIssuer { throw new AuthenticationError('No algorithm was provided in the key'); } - return new SignJWT({ iss, sub, ent, aud, iat, exp }) + return new SignJWT({ ...additionalClaims, iss, sub, ent, aud, iat, exp }) .setProtectedHeader({ alg: key.alg, kid: key.kid }) .setIssuer(iss) .setAudience(aud) diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index 4765b50d7d..49d78b8472 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -28,13 +28,19 @@ export interface AnyJWK extends Record { * @public */ export type TokenParams = { - /** The claims that will be embedded within the token */ + /** + * The claims that will be embedded within the token. At a minimum, this should include + * the subject claim, `sub`. It is common to also list entity ownership relations in the + * `ent` list. Additional claims may also be added at the developer's discretion except + * for the following list, which will be overwritten by the TokenIssuer: `iss`, `aud`, + * `iat`, and `exp`. + */ claims: { /** The token subject, i.e. User ID */ sub: string; /** A list of entity references that the user claims ownership through */ ent?: string[]; - }; + } & Record; }; /** From 5b011fb2e6aa88964fe737531fe2296e7e3f8dbb Mon Sep 17 00:00:00 2001 From: David Zemon Date: Thu, 8 Sep 2022 11:48:36 -0500 Subject: [PATCH 07/95] chore: Add changeset Signed-off-by: David Zemon --- .changeset/cold-bananas-hang.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/cold-bananas-hang.md diff --git a/.changeset/cold-bananas-hang.md b/.changeset/cold-bananas-hang.md new file mode 100644 index 0000000000..8e535a5532 --- /dev/null +++ b/.changeset/cold-bananas-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Allow adding misc claims to JWT From dba3c15c96be917c99461158a16f6a9dfafab3b0 Mon Sep 17 00:00:00 2001 From: David Zemon Date: Thu, 8 Sep 2022 12:06:23 -0500 Subject: [PATCH 08/95] chore: Add API report Signed-off-by: David Zemon --- plugins/auth-backend/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index d47abeee83..2420a79a79 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -706,7 +706,7 @@ export type TokenParams = { claims: { sub: string; ent?: string[]; - }; + } & Record; }; // @public (undocumented) From 01345242dd8b47b93b883aee2a9367159ad89b82 Mon Sep 17 00:00:00 2001 From: Axel Hecht Date: Fri, 9 Sep 2022 14:41:47 +0200 Subject: [PATCH 09/95] Update .changeset/famous-rats-heal.md Co-authored-by: Ben Lambert Signed-off-by: Axel Hecht --- .changeset/famous-rats-heal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/famous-rats-heal.md b/.changeset/famous-rats-heal.md index e233070849..4235a9fa44 100644 --- a/.changeset/famous-rats-heal.md +++ b/.changeset/famous-rats-heal.md @@ -2,4 +2,4 @@ '@backstage/plugin-catalog-backend': patch --- -Add optional value to hasAnnotation permission rule +Add optional value to `hasAnnotation` permission rule From 2270997d57f4f39f58bbfadee9dcaf7d101ee774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Mota?= Date: Fri, 9 Sep 2022 22:44:55 +0200 Subject: [PATCH 10/95] Update docker guide for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As happened to a colleague of mine and might happen to others, one might see a "docker" section and skip straight to that since it looks on the surface to be a quick way to check out backstage yourself. In this case that resulted in trying to make all these builds from the main backstage/backstage repo, before even understanding the concept of a Backstage App, which obviously did not work out. Signed-off-by: Tomás Mota --- docs/deployment/docker.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index d46aff1b06..5455babc6f 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -16,7 +16,8 @@ are stateless, so for a production deployment you will want to set up and connect to an external PostgreSQL instance where the backend plugins can store their state, rather than using SQLite. -By default, in an app created with `@backstage/create-app`, the frontend is +It is in this section assumed that an [app](https://backstage.io/docs/getting-started/create-an-app) +has already been created with`@backstage/create-app`, in which the frontend is bundled and served from the backend. This is done using the `@backstage/plugin-app-backend` plugin, which also injects the frontend configuration into the app. This means that you only need to build and deploy a From 1bdb0bf24b3b8ef134e1a475492e24aee33d42c7 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Mon, 12 Sep 2022 09:49:19 +0200 Subject: [PATCH 11/95] Modify RecentWorkflowRunsCard use constructed routeRef instead of hardcoded route. Signed-off-by: Jussi Hallila --- .changeset/brown-kings-greet.md | 5 +++++ .../components/Cards/RecentWorkflowRunsCard.tsx | 17 ++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 .changeset/brown-kings-greet.md diff --git a/.changeset/brown-kings-greet.md b/.changeset/brown-kings-greet.md new file mode 100644 index 0000000000..00e82675ee --- /dev/null +++ b/.changeset/brown-kings-greet.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-actions': patch +--- + +Modify RecentWorkflowRunsCard use constructed routeRef instead of hardcoded route. diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx index fcd0f194a3..931b5b676e 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.tsx @@ -16,19 +16,25 @@ import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { useEntity } from '@backstage/plugin-catalog-react'; import React, { useEffect } from 'react'; -import { generatePath, Link as RouterLink } from 'react-router-dom'; +import { Link as RouterLink } from 'react-router-dom'; import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity'; import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { Typography } from '@material-ui/core'; -import { configApiRef, errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { + configApiRef, + errorApiRef, + useApi, + useRouteRef, +} from '@backstage/core-plugin-api'; import { InfoCard, InfoCardVariants, Link, Table, } from '@backstage/core-components'; +import { buildRouteRef } from '../../routes'; const firstLine = (message: string): string => message.split('\n')[0]; @@ -69,7 +75,7 @@ export const RecentWorkflowRunsCard = (props: { }, [error, errorApi]); const githubHost = hostname || 'github.com'; - + const routeLink = useRouteRef(buildRouteRef); return ( ( - + {firstLine(data.message ?? '')} ), From 3d184f17130506397f300a57e2fe6e9a6653abc9 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Mon, 12 Sep 2022 09:56:52 +0200 Subject: [PATCH 12/95] Add routes to tests. Signed-off-by: Jussi Hallila --- .../Cards/RecentWorkflowRunsCard.test.tsx | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 7a20501072..5e0a5f3e15 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -15,21 +15,19 @@ */ import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; -import { render } from '@testing-library/react'; import React from 'react'; -import { MemoryRouter } from 'react-router'; import { useWorkflowRuns } from '../useWorkflowRuns'; import { RecentWorkflowRunsCard } from './RecentWorkflowRunsCard'; import { ConfigReader } from '@backstage/core-app-api'; import { - errorApiRef, - configApiRef, ConfigApi, + configApiRef, + errorApiRef, } from '@backstage/core-plugin-api'; -import { TestApiProvider } from '@backstage/test-utils'; +import { TestApiProvider, wrapInTestApp } from '@backstage/test-utils'; +import { rootRouteRef } from '../../routes'; +import { render } from '@testing-library/react'; jest.mock('../useWorkflowRuns', () => ({ useWorkflowRuns: jest.fn(), @@ -76,24 +74,27 @@ describe('', () => { const renderSubject = (props: any = {}) => render( - - - - - - - - - , + wrapInTestApp( + + + + + , + { + mountedRoutes: { + '/ci-cd': rootRouteRef, + }, + }, + ), ); it('renders a table with a row for each workflow', async () => { - const subject = renderSubject(); + const subject = await renderSubject(); workflowRuns.forEach(run => { expect(subject.getByText(run.message)).toBeInTheDocument(); @@ -101,7 +102,7 @@ describe('', () => { }); it('renders a workflow row correctly', async () => { - const subject = renderSubject(); + const subject = await renderSubject(); const [run] = workflowRuns; expect(subject.getByText(run.message).closest('a')).toHaveAttribute( 'href', From 65c990705dfc3a8c396826e7d6cd2388cc955dd8 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Mon, 12 Sep 2022 10:01:54 +0200 Subject: [PATCH 13/95] Modify changeset wording to appease vale. Signed-off-by: Jussi Hallila --- .changeset/brown-kings-greet.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.changeset/brown-kings-greet.md b/.changeset/brown-kings-greet.md index 00e82675ee..918474baf7 100644 --- a/.changeset/brown-kings-greet.md +++ b/.changeset/brown-kings-greet.md @@ -1,5 +1,6 @@ ---- +4--- '@backstage/plugin-github-actions': patch + --- -Modify RecentWorkflowRunsCard use constructed routeRef instead of hardcoded route. +Modify RecentWorkflowRunsCard use constructed route instead of hardcoded route. From 83b1b5ee5b899507bf1d6808e56db565a7091410 Mon Sep 17 00:00:00 2001 From: Jussi Hallila Date: Mon, 12 Sep 2022 10:09:29 +0200 Subject: [PATCH 14/95] Remove extra character. Signed-off-by: Jussi Hallila --- .changeset/brown-kings-greet.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.changeset/brown-kings-greet.md b/.changeset/brown-kings-greet.md index 918474baf7..8271b40bb4 100644 --- a/.changeset/brown-kings-greet.md +++ b/.changeset/brown-kings-greet.md @@ -1,6 +1,5 @@ -4--- +--- '@backstage/plugin-github-actions': patch - --- Modify RecentWorkflowRunsCard use constructed route instead of hardcoded route. From f52dfc0c485f7c7cc0763bb89b978828895bc021 Mon Sep 17 00:00:00 2001 From: sblausten Date: Mon, 12 Sep 2022 11:56:23 +0100 Subject: [PATCH 15/95] Fix overflow issue for mic drop image Signed-off-by: sblausten --- packages/core-components/src/layout/ErrorPage/ErrorPage.tsx | 2 +- packages/core-components/src/layout/ErrorPage/MicDrop.tsx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx index 928a3eb0d4..658c06de2a 100644 --- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx @@ -70,7 +70,6 @@ export function ErrorPage(props: IErrorPageProps) { return ( - + ); } diff --git a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx index efa101b23b..aacb44079a 100644 --- a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx +++ b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx @@ -22,12 +22,10 @@ const useStyles = makeStyles( theme => ({ micDrop: { maxWidth: '60%', - position: 'absolute', bottom: theme.spacing(2), right: theme.spacing(2), [theme.breakpoints.down('xs')]: { maxWidth: '96%', - position: 'relative', bottom: 'unset', right: 'unset', margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`, From 023d14c52b03d530de1dd257cd199e9caafd37d7 Mon Sep 17 00:00:00 2001 From: sblausten Date: Mon, 12 Sep 2022 13:03:50 +0100 Subject: [PATCH 16/95] changeset Signed-off-by: sblausten --- .changeset/three-dryers-confess.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/three-dryers-confess.md diff --git a/.changeset/three-dryers-confess.md b/.changeset/three-dryers-confess.md new file mode 100644 index 0000000000..e68bc36665 --- /dev/null +++ b/.changeset/three-dryers-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix overflow bug on MicDrop image for 404 page by moving the image and making it relative rather than absolute From da9547d2f34b14dfdbcf33958cf34466fa94f056 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 13 Sep 2022 08:56:36 +0000 Subject: [PATCH 17/95] Version Packages (next) --- .changeset/pre.json | 25 + docs/releases/v1.6.0-next.3-changelog.md | 1768 ++++++++++++ package.json | 2 +- packages/app-defaults/CHANGELOG.md | 12 + packages/app-defaults/package.json | 14 +- packages/app/CHANGELOG.md | 56 + packages/app/package.json | 104 +- packages/backend-app-api/CHANGELOG.md | 13 + packages/backend-app-api/package.json | 14 +- packages/backend-common/CHANGELOG.md | 12 + packages/backend-common/package.json | 16 +- packages/backend-defaults/CHANGELOG.md | 9 + packages/backend-defaults/package.json | 8 +- packages/backend-plugin-api/CHANGELOG.md | 12 + packages/backend-plugin-api/package.json | 12 +- packages/backend-tasks/CHANGELOG.md | 9 + packages/backend-tasks/package.json | 12 +- packages/backend-test-utils/CHANGELOG.md | 12 + packages/backend-test-utils/package.json | 14 +- packages/backend/CHANGELOG.md | 40 + packages/backend/package.json | 70 +- packages/catalog-client/CHANGELOG.md | 13 + packages/catalog-client/package.json | 8 +- packages/catalog-model/CHANGELOG.md | 9 + packages/catalog-model/package.json | 8 +- packages/cli-common/CHANGELOG.md | 6 + packages/cli-common/package.json | 4 +- packages/cli/CHANGELOG.md | 13 + packages/cli/package.json | 26 +- packages/codemods/CHANGELOG.md | 7 + packages/codemods/package.json | 6 +- packages/config-loader/CHANGELOG.md | 11 + packages/config-loader/package.json | 10 +- packages/config/CHANGELOG.md | 6 + packages/config/package.json | 6 +- packages/core-app-api/CHANGELOG.md | 9 + packages/core-app-api/package.json | 10 +- packages/core-components/CHANGELOG.md | 10 + packages/core-components/package.json | 14 +- packages/core-plugin-api/CHANGELOG.md | 8 + packages/core-plugin-api/package.json | 10 +- packages/create-app/CHANGELOG.md | 8 + packages/create-app/package.json | 6 +- packages/dev-utils/CHANGELOG.md | 16 + packages/dev-utils/package.json | 20 +- packages/e2e-test/package.json | 6 +- packages/errors/CHANGELOG.md | 6 + packages/errors/package.json | 4 +- packages/integration-react/CHANGELOG.md | 11 + packages/integration-react/package.json | 16 +- packages/integration/CHANGELOG.md | 13 + packages/integration/package.json | 12 +- packages/release-manifests/CHANGELOG.md | 6 + packages/release-manifests/package.json | 6 +- .../techdocs-cli-embedded-app/CHANGELOG.md | 18 + .../techdocs-cli-embedded-app/package.json | 28 +- packages/techdocs-cli/CHANGELOG.md | 12 + packages/techdocs-cli/package.json | 14 +- packages/test-utils/CHANGELOG.md | 13 + packages/test-utils/package.json | 14 +- plugins/adr-backend/CHANGELOG.md | 13 + plugins/adr-backend/package.json | 18 +- plugins/adr-common/CHANGELOG.md | 8 + plugins/adr-common/package.json | 8 +- plugins/adr/CHANGELOG.md | 13 + plugins/adr/package.json | 22 +- plugins/airbrake-backend/CHANGELOG.md | 8 + plugins/airbrake-backend/package.json | 8 +- plugins/airbrake/CHANGELOG.md | 13 + plugins/airbrake/package.json | 22 +- plugins/allure/CHANGELOG.md | 11 + plugins/allure/package.json | 18 +- plugins/analytics-module-ga/CHANGELOG.md | 10 + plugins/analytics-module-ga/package.json | 16 +- plugins/apache-airflow/CHANGELOG.md | 9 + plugins/apache-airflow/package.json | 14 +- plugins/api-docs/CHANGELOG.md | 12 + plugins/api-docs/package.json | 20 +- plugins/apollo-explorer/CHANGELOG.md | 9 + plugins/apollo-explorer/package.json | 14 +- plugins/app-backend/CHANGELOG.md | 9 + plugins/app-backend/package.json | 12 +- plugins/auth-backend/CHANGELOG.md | 18 + plugins/auth-backend/package.json | 18 +- plugins/auth-node/CHANGELOG.md | 9 + plugins/auth-node/package.json | 12 +- plugins/azure-devops-backend/CHANGELOG.md | 8 + plugins/azure-devops-backend/package.json | 8 +- plugins/azure-devops/CHANGELOG.md | 12 + plugins/azure-devops/package.json | 20 +- plugins/badges-backend/CHANGELOG.md | 11 + plugins/badges-backend/package.json | 14 +- plugins/badges/CHANGELOG.md | 12 + plugins/badges/package.json | 20 +- plugins/bazaar-backend/CHANGELOG.md | 9 + plugins/bazaar-backend/package.json | 10 +- plugins/bazaar/CHANGELOG.md | 14 + plugins/bazaar/package.json | 20 +- plugins/bitrise/CHANGELOG.md | 11 + plugins/bitrise/package.json | 18 +- .../catalog-backend-module-aws/CHANGELOG.md | 13 + .../catalog-backend-module-aws/package.json | 18 +- .../catalog-backend-module-azure/CHANGELOG.md | 13 + .../catalog-backend-module-azure/package.json | 20 +- .../CHANGELOG.md | 10 + .../package.json | 16 +- .../CHANGELOG.md | 13 + .../package.json | 20 +- .../CHANGELOG.md | 12 + .../package.json | 18 +- .../CHANGELOG.md | 13 + .../package.json | 20 +- .../CHANGELOG.md | 15 + .../package.json | 24 +- .../CHANGELOG.md | 13 + .../package.json | 20 +- .../catalog-backend-module-ldap/CHANGELOG.md | 11 + .../catalog-backend-module-ldap/package.json | 14 +- .../CHANGELOG.md | 11 + .../package.json | 16 +- .../CHANGELOG.md | 12 + .../package.json | 18 +- plugins/catalog-backend/CHANGELOG.md | 21 + plugins/catalog-backend/package.json | 32 +- plugins/catalog-graph/CHANGELOG.md | 12 + plugins/catalog-graph/package.json | 22 +- plugins/catalog-graphql/CHANGELOG.md | 8 + plugins/catalog-graphql/package.json | 10 +- plugins/catalog-import/CHANGELOG.md | 16 + plugins/catalog-import/package.json | 28 +- plugins/catalog-node/CHANGELOG.md | 15 + plugins/catalog-node/package.json | 16 +- plugins/catalog-react/CHANGELOG.md | 17 + plugins/catalog-react/package.json | 26 +- plugins/catalog/CHANGELOG.md | 14 + plugins/catalog/package.json | 26 +- .../CHANGELOG.md | 9 + .../package.json | 10 +- plugins/cicd-statistics/CHANGELOG.md | 9 + plugins/cicd-statistics/package.json | 10 +- plugins/circleci/CHANGELOG.md | 11 + plugins/circleci/package.json | 18 +- plugins/cloudbuild/CHANGELOG.md | 11 + plugins/cloudbuild/package.json | 18 +- plugins/code-climate/CHANGELOG.md | 11 + plugins/code-climate/package.json | 16 +- plugins/code-coverage-backend/CHANGELOG.md | 12 + plugins/code-coverage-backend/package.json | 16 +- plugins/code-coverage/CHANGELOG.md | 13 + plugins/code-coverage/package.json | 22 +- plugins/codescene/CHANGELOG.md | 11 + plugins/codescene/package.json | 18 +- plugins/config-schema/CHANGELOG.md | 11 + plugins/config-schema/package.json | 18 +- plugins/cost-insights/CHANGELOG.md | 11 + plugins/cost-insights/package.json | 18 +- plugins/dynatrace/CHANGELOG.md | 10 + plugins/dynatrace/package.json | 16 +- .../example-todo-list-backend/CHANGELOG.md | 10 + .../example-todo-list-backend/package.json | 12 +- plugins/explore-react/CHANGELOG.md | 8 + plugins/explore-react/package.json | 10 +- plugins/explore/CHANGELOG.md | 12 + plugins/explore/package.json | 20 +- plugins/firehydrant/CHANGELOG.md | 10 + plugins/firehydrant/package.json | 16 +- plugins/fossa/CHANGELOG.md | 12 + plugins/fossa/package.json | 20 +- plugins/gcalendar/CHANGELOG.md | 10 + plugins/gcalendar/package.json | 16 +- plugins/gcp-projects/CHANGELOG.md | 9 + plugins/gcp-projects/package.json | 14 +- plugins/git-release-manager/CHANGELOG.md | 10 + plugins/git-release-manager/package.json | 16 +- plugins/github-actions/CHANGELOG.md | 12 + plugins/github-actions/package.json | 20 +- plugins/github-deployments/CHANGELOG.md | 14 + plugins/github-deployments/package.json | 24 +- plugins/github-issues/CHANGELOG.md | 13 + plugins/github-issues/package.json | 22 +- .../github-pull-requests-board/CHANGELOG.md | 12 + .../github-pull-requests-board/package.json | 18 +- plugins/gitops-profiles/CHANGELOG.md | 9 + plugins/gitops-profiles/package.json | 14 +- plugins/gocd/CHANGELOG.md | 12 + plugins/gocd/package.json | 20 +- plugins/graphiql/CHANGELOG.md | 9 + plugins/graphiql/package.json | 14 +- plugins/graphql-backend/CHANGELOG.md | 9 + plugins/graphql-backend/package.json | 10 +- plugins/home/CHANGELOG.md | 13 + plugins/home/package.json | 22 +- plugins/ilert/CHANGELOG.md | 12 + plugins/ilert/package.json | 20 +- plugins/jenkins-backend/CHANGELOG.md | 13 + plugins/jenkins-backend/package.json | 18 +- plugins/jenkins/CHANGELOG.md | 12 + plugins/jenkins/package.json | 20 +- plugins/kafka-backend/CHANGELOG.md | 10 + plugins/kafka-backend/package.json | 12 +- plugins/kafka/CHANGELOG.md | 12 + plugins/kafka/package.json | 20 +- plugins/kubernetes-backend/CHANGELOG.md | 13 + plugins/kubernetes-backend/package.json | 18 +- plugins/kubernetes-common/CHANGELOG.md | 7 + plugins/kubernetes-common/package.json | 6 +- plugins/kubernetes/CHANGELOG.md | 14 + plugins/kubernetes/package.json | 22 +- plugins/lighthouse/CHANGELOG.md | 12 + plugins/lighthouse/package.json | 20 +- plugins/newrelic-dashboard/CHANGELOG.md | 11 + plugins/newrelic-dashboard/package.json | 16 +- plugins/newrelic/CHANGELOG.md | 9 + plugins/newrelic/package.json | 14 +- plugins/org/CHANGELOG.md | 11 + plugins/org/package.json | 20 +- plugins/pagerduty/CHANGELOG.md | 12 + plugins/pagerduty/package.json | 20 +- plugins/periskop-backend/CHANGELOG.md | 8 + plugins/periskop-backend/package.json | 8 +- plugins/periskop/CHANGELOG.md | 12 + plugins/periskop/package.json | 20 +- plugins/permission-backend/CHANGELOG.md | 12 + plugins/permission-backend/package.json | 16 +- plugins/permission-common/CHANGELOG.md | 9 + plugins/permission-common/package.json | 8 +- plugins/permission-node/CHANGELOG.md | 11 + plugins/permission-node/package.json | 16 +- plugins/permission-react/CHANGELOG.md | 10 + plugins/permission-react/package.json | 12 +- plugins/proxy-backend/CHANGELOG.md | 8 + plugins/proxy-backend/package.json | 8 +- plugins/rollbar-backend/CHANGELOG.md | 8 + plugins/rollbar-backend/package.json | 10 +- plugins/rollbar/CHANGELOG.md | 11 + plugins/rollbar/package.json | 18 +- .../CHANGELOG.md | 12 + .../package.json | 14 +- .../CHANGELOG.md | 12 + .../package.json | 14 +- .../CHANGELOG.md | 9 + .../package.json | 10 +- plugins/scaffolder-backend/CHANGELOG.md | 18 + plugins/scaffolder-backend/package.json | 28 +- plugins/scaffolder-common/CHANGELOG.md | 7 + plugins/scaffolder-common/package.json | 6 +- plugins/scaffolder/CHANGELOG.md | 20 + plugins/scaffolder/package.json | 34 +- .../CHANGELOG.md | 8 + .../package.json | 10 +- plugins/search-backend-module-pg/CHANGELOG.md | 9 + plugins/search-backend-module-pg/package.json | 12 +- plugins/search-backend-node/CHANGELOG.md | 11 + plugins/search-backend-node/package.json | 16 +- plugins/search-backend/CHANGELOG.md | 13 + plugins/search-backend/package.json | 18 +- plugins/search/CHANGELOG.md | 13 + plugins/search/package.json | 22 +- plugins/sentry/CHANGELOG.md | 11 + plugins/sentry/package.json | 18 +- plugins/shortcuts/CHANGELOG.md | 9 + plugins/shortcuts/package.json | 14 +- plugins/sonarqube-backend/CHANGELOG.md | 9 + plugins/sonarqube-backend/package.json | 12 +- plugins/sonarqube/CHANGELOG.md | 11 + plugins/sonarqube/package.json | 18 +- plugins/splunk-on-call/CHANGELOG.md | 11 + plugins/splunk-on-call/package.json | 18 +- plugins/stack-overflow-backend/CHANGELOG.md | 8 + plugins/stack-overflow-backend/package.json | 6 +- plugins/stack-overflow/CHANGELOG.md | 11 + plugins/stack-overflow/package.json | 18 +- .../CHANGELOG.md | 10 + .../package.json | 12 +- plugins/tech-insights-backend/CHANGELOG.md | 13 + plugins/tech-insights-backend/package.json | 20 +- plugins/tech-insights-node/CHANGELOG.md | 9 + plugins/tech-insights-node/package.json | 10 +- plugins/tech-insights/CHANGELOG.md | 12 + plugins/tech-insights/package.json | 20 +- plugins/tech-radar/CHANGELOG.md | 9 + plugins/tech-radar/package.json | 14 +- .../techdocs-addons-test-utils/CHANGELOG.md | 15 + .../techdocs-addons-test-utils/package.json | 22 +- plugins/techdocs-backend/CHANGELOG.md | 14 + plugins/techdocs-backend/package.json | 24 +- .../CHANGELOG.md | 12 + .../package.json | 22 +- plugins/techdocs-node/CHANGELOG.md | 11 + plugins/techdocs-node/package.json | 14 +- plugins/techdocs-react/CHANGELOG.md | 10 + plugins/techdocs-react/package.json | 14 +- plugins/techdocs/CHANGELOG.md | 16 + plugins/techdocs/package.json | 28 +- plugins/todo-backend/CHANGELOG.md | 12 + plugins/todo-backend/package.json | 16 +- plugins/todo/CHANGELOG.md | 12 + plugins/todo/package.json | 20 +- plugins/user-settings/CHANGELOG.md | 9 + plugins/user-settings/package.json | 14 +- plugins/vault-backend/CHANGELOG.md | 11 + plugins/vault-backend/package.json | 14 +- plugins/vault/CHANGELOG.md | 12 + plugins/vault/package.json | 20 +- plugins/xcmetrics/CHANGELOG.md | 10 + plugins/xcmetrics/package.json | 16 +- yarn.lock | 2484 +++++++++-------- 307 files changed, 6104 insertions(+), 2508 deletions(-) create mode 100644 docs/releases/v1.6.0-next.3-changelog.md diff --git a/.changeset/pre.json b/.changeset/pre.json index 96664632fd..028a1a665f 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -188,19 +188,24 @@ "clever-turtles-work", "cold-frogs-kiss", "cool-cameras-count", + "cuddly-clocks-dance", "cuddly-needles-marry", "curly-hounds-wait", "dry-games-end", "dry-tips-build", "dull-spoons-doubt", + "eight-shrimps-call", "eight-spies-protect", "eleven-bees-marry", + "empty-colts-whisper", "famous-cups-roll", "famous-hounds-sit", "famous-pianos-kick", "famous-wombats-happen", "fast-paws-press", "five-carrots-pay", + "flat-crabs-love", + "flat-humans-dance", "flat-plums-shout", "flat-walls-kiss", "fresh-rabbits-juggle", @@ -211,17 +216,21 @@ "gold-laws-attend", "good-avocados-grow", "good-papayas-dress", + "gorgeous-boats-prove", + "gorgeous-pillows-retire", "gorgeous-swans-kiss", "great-cats-sit", "great-rules-march", "grumpy-kiwis-juggle", "happy-kiwis-look", "heavy-ligers-laugh", + "hot-brooms-drive", "hot-files-begin", "hot-suits-glow", "hungry-dogs-agree", "itchy-brooms-end", "itchy-kiwis-warn", + "large-books-deny", "large-eagles-shop", "large-trainers-float", "late-turtles-listen", @@ -230,13 +239,17 @@ "light-donuts-obey", "loud-comics-search", "lovely-ants-invite", + "lucky-ads-worry", "lucky-points-wash", "many-rules-raise", "mean-tomatoes-visit", + "metal-candles-tease", "metal-crabs-wash", + "metal-weeks-kiss", "moody-berries-sneeze", "neat-kangaroos-turn", "nervous-rivers-sneeze", + "new-taxis-vanish", "old-lemons-switch", "old-readers-provide", "old-rockets-doubt", @@ -247,7 +260,9 @@ "purple-jeans-bathe", "purple-plums-travel", "purple-wolves-confess", + "quick-items-invite", "quick-lamps-talk", + "rare-tips-glow", "red-numbers-suffer", "renovate-16f36a0", "renovate-1a6cc1f", @@ -263,6 +278,7 @@ "rotten-books-crash", "rude-books-rush", "rude-tips-argue", + "rude-weeks-retire", "search-feet-flash", "search-planets-flash", "search-zebras-tap", @@ -273,11 +289,14 @@ "shiny-lobsters-fix", "shiny-ties-leave", "shiny-walls-kiss", + "short-mice-explode", "silent-kings-live", "slimy-stingrays-type", "slimy-zebras-reply", + "slow-phones-count", "small-lemons-brake", "small-walls-promise", + "smart-sloths-search", "smart-squids-change", "smooth-yaks-hug", "spicy-cherries-remember", @@ -286,10 +305,13 @@ "strong-planes-return", "stupid-pigs-appear", "sweet-fishes-taste", + "sweet-grapes-explain", "swift-readers-sin", "tall-trains-remain", "tame-papayas-protect", + "tame-socks-sniff", "tame-trainers-rule", + "tasty-clouds-cover", "techdocs-feet-dress", "techdocs-jeans-wait", "tender-ladybugs-relax", @@ -298,13 +320,16 @@ "tiny-oranges-thank", "tiny-rocks-flash", "tough-dolphins-smile", + "twenty-dolls-smoke", "two-planets-provide", "veka-fingrar-drar", "weak-camels-roll", + "weak-radios-sin", "weak-yaks-learn", "wild-sheep-roll", "witty-cats-wink", "witty-queens-happen", + "young-falcons-sleep", "young-trees-rescue" ] } diff --git a/docs/releases/v1.6.0-next.3-changelog.md b/docs/releases/v1.6.0-next.3-changelog.md new file mode 100644 index 0000000000..9cf02ac93f --- /dev/null +++ b/docs/releases/v1.6.0-next.3-changelog.md @@ -0,0 +1,1768 @@ +# Release v1.6.0-next.3 + +## @backstage/catalog-client@1.1.0-next.2 + +### Minor Changes + +- 65d1d4343f: Adding `validateEntity` method that calls `/validate-entity` endpoint. + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-auth-backend@0.16.0-next.3 + +### Minor Changes + +- 8600855fbf: The auth0 integration is updated to use the `passport-auth0` library. The configuration under `auth.providers.auth0.\*` now supports an optional `audience` parameter; providing that allows you to connect to the correct API to get permissions, access tokens, and full profile information. + + [What is an Audience](https://community.auth0.com/t/what-is-the-audience/71414) + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + +## @backstage/plugin-catalog-backend@1.4.0-next.3 + +### Minor Changes + +- 6e63bc43f2: Added the `refresh` function to the Connection of the entity providers. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + - @backstage/plugin-permission-node@0.6.5-next.3 + +## @backstage/plugin-catalog-node@1.1.0-next.2 + +### Minor Changes + +- 9743bc788c: Added refresh function to the `EntityProviderConnection` to be able to schedule refreshes from entity providers. + +### Patch Changes + +- 409ed984e8: Updated usage of experimental backend service APIs. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/app-defaults@1.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- d9e39544be: Add missing peer dependencies +- Updated dependencies + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-react@0.4.5-next.2 + +## @backstage/backend-app-api@0.2.1-next.2 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- 409ed984e8: Updated service implementations and backend wiring to support scoped service. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-permission-node@0.6.5-next.3 + +## @backstage/backend-common@0.15.1-next.3 + +### Patch Changes + +- 96689fbdcb: Workaround for a rare race condition in tests. +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + +## @backstage/backend-defaults@0.1.1-next.1 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/backend-app-api@0.2.1-next.2 + +## @backstage/backend-plugin-api@0.1.2-next.2 + +### Patch Changes + +- 409ed984e8: Service are now scoped to either `'plugin'` or `'root'` scope. Service factories have been updated to provide dependency instances directly rather than factory functions. +- 854ba37357: The `createServiceFactory` method has been updated to return a higher-order factory that can accept options. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/backend-tasks@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/backend-test-utils@0.1.28-next.3 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-app-api@0.2.1-next.2 + - @backstage/cli@0.19.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/catalog-model@1.1.1-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/cli@0.19.0-next.3 + +### Patch Changes + +- 7d47def9c4: Added dependency on `@types/jest` v27. The `@types/jest` dependency has also been removed from the plugin template and should be removed from any of your own internal packages. If you wish to override the version of `@types/jest` or `jest`, use Yarn resolutions. +- a7e82c9b01: Updated `versions:bump` command to be compatible with Yarn 3. +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/release-manifests@0.0.6-next.2 + +## @backstage/cli-common@0.1.10-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + +## @backstage/codemods@0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + +## @backstage/config@1.0.2-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + +## @backstage/config-loader@1.1.4-next.2 + +### Patch Changes + +- 5ecca7e44b: No longer log when reloading remote config. +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/core-app-api@1.1.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/core-components@0.11.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/core-plugin-api@1.0.6-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + +## @backstage/create-app@0.4.31-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + +## @backstage/dev-utils@1.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 329ed2b9c7: Fixed routing when using React Router v6 stable. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + +## @backstage/errors@1.1.1-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + +## @backstage/integration@1.3.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- f76f22c649: Improved caching around github app tokens. + Tokens are now cached for 50 minutes, not 10. + Calls to get app installations are also included in this cache. + If you have more than one github app configured, consider adding `allowedInstallationOwners` to your apps configuration to gain the most benefit from these performance changes. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/integration-react@1.1.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + +## @backstage/release-manifests@0.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + +## @techdocs/cli@1.2.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-techdocs-node@1.4.0-next.2 + +## @backstage/test-utils@1.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- d9e39544be: Add missing peer dependencies +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + +## @backstage/plugin-adr@0.2.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-adr-common@0.2.1-next.1 + +## @backstage/plugin-adr-backend@0.2.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-adr-common@0.2.1-next.1 + +## @backstage/plugin-adr-common@0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + +## @backstage/plugin-airbrake@0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/dev-utils@1.0.6-next.2 + - @backstage/test-utils@1.2.0-next.3 + +## @backstage/plugin-airbrake-backend@0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-allure@0.1.25-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-analytics-module-ga@0.1.20-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-apache-airflow@0.2.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-api-docs@0.8.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + +## @backstage/plugin-apollo-explorer@0.1.2-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-app-backend@0.3.36-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-auth-node@0.2.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-azure-devops@0.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-azure-devops-backend@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-badges@0.2.33-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-badges-backend@0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-bazaar@0.1.24-next.2 + +### Patch Changes + +- 1dd12349d1: Fixed broken routing by removing the wrapping `Router` from the `RoutedTabs` children. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/cli@0.19.0-next.3 + +## @backstage/plugin-bazaar-backend@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-test-utils@0.1.28-next.3 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-bitrise@0.1.36-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-catalog@1.5.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration-react@1.1.4-next.2 + +## @backstage/plugin-catalog-backend-module-aws@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.4-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.4.2-next.3 + +### Patch Changes + +- d80aab31ae: Added $select attribute to user query +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-catalog-graph@0.2.21-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-catalog-graphql@0.3.13-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + +## @backstage/plugin-catalog-import@0.8.12-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + +## @backstage/plugin-catalog-react@1.1.4-next.2 + +### Patch Changes + +- f6033d1121: humanizeEntityRef function can now be forced to include default namespace +- c86741a052: Support showing counts in option labels of the `EntityTagPicker`. You can enable this by adding the `showCounts` property +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + +## @backstage/plugin-cicd-statistics@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-cicd-statistics@0.1.11-next.2 + +## @backstage/plugin-circleci@0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-cloudbuild@0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-code-climate@0.1.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-code-coverage@0.2.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-codescene@0.1.4-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-config-schema@0.1.32-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-cost-insights@0.11.31-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-dynatrace@0.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-explore@0.3.40-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-explore-react@0.0.21-next.3 + +## @backstage/plugin-explore-react@0.0.21-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-firehydrant@0.1.26-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-fossa@0.2.41-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-gcalendar@0.3.5-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-gcp-projects@0.3.28-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-git-release-manager@0.3.22-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + +## @backstage/plugin-github-actions@0.5.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + +## @backstage/plugin-github-deployments@0.1.40-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + +## @backstage/plugin-github-issues@0.1.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + +## @backstage/plugin-github-pull-requests-board@0.1.3-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + +## @backstage/plugin-gitops-profiles@0.3.27-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-gocd@0.1.15-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-graphiql@0.2.41-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-graphql-backend@0.1.26-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-catalog-graphql@0.3.13-next.3 + +## @backstage/plugin-home@0.4.25-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-stack-overflow@0.1.5-next.3 + +## @backstage/plugin-ilert@0.1.35-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-jenkins@0.7.8-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-jenkins-backend@0.1.26-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + +## @backstage/plugin-kafka@0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-kafka-backend@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-kubernetes@0.7.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 19a27929fb: Reset error state on success +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-kubernetes-common@0.4.2-next.1 + +## @backstage/plugin-kubernetes-backend@0.7.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-kubernetes-common@0.4.2-next.1 + - @backstage/plugin-auth-node@0.2.5-next.3 + +## @backstage/plugin-kubernetes-common@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + +## @backstage/plugin-lighthouse@0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-newrelic@0.3.27-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-newrelic-dashboard@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-org@0.5.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-pagerduty@0.5.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-periskop@0.1.7-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-periskop-backend@0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-permission-backend@0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-permission-node@0.6.5-next.3 + +## @backstage/plugin-permission-common@0.6.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-permission-node@0.6.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + +## @backstage/plugin-permission-react@0.4.5-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-common@0.6.4-next.2 + +## @backstage/plugin-proxy-backend@0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-rollbar@0.4.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-rollbar-backend@0.1.33-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-scaffolder@1.6.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 6522e459aa: Support displaying and ordering by counts in `EntityTagPicker` field. Add the `showCounts` option to enable this. Also support configuring `helperText`. +- f0510a20b5: Addition of a dismissible Error Banner in Scaffolder page +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + +## @backstage/plugin-scaffolder-backend@1.6.0-next.3 + +### Patch Changes + +- 50467bc15b: The number of task workers used to execute templates now default to 3, rather than 1. +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.5-next.3 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.11-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.4-next.1 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.9-next.1 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + +## @backstage/plugin-scaffolder-common@1.2.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + +## @backstage/plugin-search@1.0.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-search-backend@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-permission-node@0.6.5-next.3 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + +## @backstage/plugin-search-backend-module-elasticsearch@1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + +## @backstage/plugin-search-backend-module-pg@0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + +## @backstage/plugin-search-backend-node@1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-sentry@0.4.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-shortcuts@0.3.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-sonarqube@0.4.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-sonarqube-backend@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-splunk-on-call@0.3.33-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-stack-overflow@0.1.5-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-home@0.4.25-next.3 + +## @backstage/plugin-stack-overflow-backend@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/cli@0.19.0-next.3 + +## @backstage/plugin-tech-insights@0.3.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-tech-insights-backend@0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + +## @backstage/plugin-tech-insights-node@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-tech-radar@0.5.16-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-techdocs@1.3.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.4-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + +## @backstage/plugin-techdocs-backend@1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-techdocs-node@1.4.0-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.0.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + +## @backstage/plugin-techdocs-node@1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-techdocs-react@1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-todo@0.2.11-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-todo-backend@0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + +## @backstage/plugin-user-settings@0.4.8-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + +## @backstage/plugin-vault@0.1.3-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## @backstage/plugin-vault-backend@0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-test-utils@0.1.28-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + +## @backstage/plugin-xcmetrics@0.2.29-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + +## example-app@0.2.75-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-airbrake@0.3.9-next.3 + - @backstage/plugin-apache-airflow@0.2.2-next.3 + - @backstage/plugin-api-docs@0.8.9-next.3 + - @backstage/plugin-azure-devops@0.2.0-next.3 + - @backstage/plugin-badges@0.2.33-next.3 + - @backstage/plugin-catalog-graph@0.2.21-next.2 + - @backstage/plugin-catalog-import@0.8.12-next.3 + - @backstage/plugin-circleci@0.3.9-next.3 + - @backstage/plugin-cloudbuild@0.3.9-next.3 + - @backstage/plugin-code-coverage@0.2.2-next.3 + - @backstage/plugin-cost-insights@0.11.31-next.3 + - @backstage/plugin-dynatrace@0.2.0-next.3 + - @backstage/plugin-explore@0.3.40-next.3 + - @backstage/plugin-gcalendar@0.3.5-next.3 + - @backstage/plugin-gcp-projects@0.3.28-next.3 + - @backstage/plugin-github-actions@0.5.9-next.3 + - @backstage/plugin-gocd@0.1.15-next.2 + - @backstage/plugin-graphiql@0.2.41-next.3 + - @backstage/plugin-home@0.4.25-next.3 + - @backstage/plugin-jenkins@0.7.8-next.3 + - @backstage/plugin-kafka@0.3.9-next.3 + - @backstage/plugin-kubernetes@0.7.2-next.3 + - @backstage/plugin-lighthouse@0.3.9-next.3 + - @backstage/plugin-newrelic@0.3.27-next.3 + - @backstage/plugin-org@0.5.9-next.3 + - @backstage/plugin-pagerduty@0.5.2-next.3 + - @backstage/plugin-permission-react@0.4.5-next.2 + - @backstage/plugin-rollbar@0.4.9-next.3 + - @backstage/plugin-scaffolder@1.6.0-next.3 + - @backstage/plugin-search@1.0.2-next.3 + - @backstage/plugin-sentry@0.4.2-next.3 + - @backstage/plugin-shortcuts@0.3.1-next.3 + - @backstage/plugin-stack-overflow@0.1.5-next.3 + - @backstage/plugin-tech-insights@0.3.0-next.3 + - @backstage/plugin-tech-radar@0.5.16-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.4-next.2 + - @backstage/plugin-todo@0.2.11-next.3 + - @backstage/plugin-user-settings@0.4.8-next.3 + - @backstage/cli@0.19.0-next.3 + - @backstage/plugin-newrelic-dashboard@0.2.2-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + +## example-backend@0.2.75-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.4-next.1 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/plugin-auth-backend@0.16.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + - @backstage/plugin-badges-backend@0.1.30-next.1 + - @backstage/plugin-code-coverage-backend@0.2.2-next.2 + - @backstage/plugin-jenkins-backend@0.1.26-next.3 + - @backstage/plugin-kubernetes-backend@0.7.2-next.3 + - @backstage/plugin-tech-insights-backend@0.5.2-next.2 + - @backstage/plugin-techdocs-backend@1.3.0-next.2 + - @backstage/plugin-todo-backend@0.1.33-next.2 + - example-app@0.2.75-next.3 + - @backstage/plugin-kafka-backend@0.2.29-next.1 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-app-backend@0.3.36-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-azure-devops-backend@0.3.15-next.2 + - @backstage/plugin-graphql-backend@0.1.26-next.3 + - @backstage/plugin-permission-backend@0.5.11-next.2 + - @backstage/plugin-permission-node@0.6.5-next.3 + - @backstage/plugin-proxy-backend@0.2.30-next.2 + - @backstage/plugin-rollbar-backend@0.1.33-next.3 + - @backstage/plugin-search-backend@1.0.2-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.0.2-next.2 + - @backstage/plugin-search-backend-module-pg@0.4.0-next.2 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.20-next.1 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + +## techdocs-cli-embedded-app@0.2.74-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/cli@0.19.0-next.3 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + +## @internal/plugin-todo-list-backend@1.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 diff --git a/package.json b/package.json index 3c9e2743cb..a0de99bfad 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@types/react": "^17", "@types/react-dom": "^17" }, - "version": "1.6.0-next.2", + "version": "1.6.0-next.3", "dependencies": { "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.17.11", diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 799c380dbc..c9216bf2a4 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/app-defaults +## 1.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- d9e39544be: Add missing peer dependencies +- Updated dependencies + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-react@0.4.5-next.2 + ## 1.0.6-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 355a7ee77e..c83e31b057 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.0.6-next.1", + "version": "1.0.6-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,10 +32,10 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-app-api": "^1.1.0-next.1", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-permission-react": "^0.4.5-next.1", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-permission-react": "^0.4.5-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1" @@ -47,8 +47,8 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@types/node": "^16.11.26", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index ec851aa8d0..f763210b27 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,61 @@ # example-app +## 0.2.75-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-airbrake@0.3.9-next.3 + - @backstage/plugin-apache-airflow@0.2.2-next.3 + - @backstage/plugin-api-docs@0.8.9-next.3 + - @backstage/plugin-azure-devops@0.2.0-next.3 + - @backstage/plugin-badges@0.2.33-next.3 + - @backstage/plugin-catalog-graph@0.2.21-next.2 + - @backstage/plugin-catalog-import@0.8.12-next.3 + - @backstage/plugin-circleci@0.3.9-next.3 + - @backstage/plugin-cloudbuild@0.3.9-next.3 + - @backstage/plugin-code-coverage@0.2.2-next.3 + - @backstage/plugin-cost-insights@0.11.31-next.3 + - @backstage/plugin-dynatrace@0.2.0-next.3 + - @backstage/plugin-explore@0.3.40-next.3 + - @backstage/plugin-gcalendar@0.3.5-next.3 + - @backstage/plugin-gcp-projects@0.3.28-next.3 + - @backstage/plugin-github-actions@0.5.9-next.3 + - @backstage/plugin-gocd@0.1.15-next.2 + - @backstage/plugin-graphiql@0.2.41-next.3 + - @backstage/plugin-home@0.4.25-next.3 + - @backstage/plugin-jenkins@0.7.8-next.3 + - @backstage/plugin-kafka@0.3.9-next.3 + - @backstage/plugin-kubernetes@0.7.2-next.3 + - @backstage/plugin-lighthouse@0.3.9-next.3 + - @backstage/plugin-newrelic@0.3.27-next.3 + - @backstage/plugin-org@0.5.9-next.3 + - @backstage/plugin-pagerduty@0.5.2-next.3 + - @backstage/plugin-permission-react@0.4.5-next.2 + - @backstage/plugin-rollbar@0.4.9-next.3 + - @backstage/plugin-scaffolder@1.6.0-next.3 + - @backstage/plugin-search@1.0.2-next.3 + - @backstage/plugin-sentry@0.4.2-next.3 + - @backstage/plugin-shortcuts@0.3.1-next.3 + - @backstage/plugin-stack-overflow@0.1.5-next.3 + - @backstage/plugin-tech-insights@0.3.0-next.3 + - @backstage/plugin-tech-radar@0.5.16-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/plugin-techdocs-module-addons-contrib@1.0.4-next.2 + - @backstage/plugin-todo@0.2.11-next.3 + - @backstage/plugin-user-settings@0.4.8-next.3 + - @backstage/cli@0.19.0-next.3 + - @backstage/plugin-newrelic-dashboard@0.2.2-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + ## 0.2.75-next.2 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index e9c9632d81..df68e1032c 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,65 +1,65 @@ { "name": "example-app", - "version": "0.2.75-next.2", + "version": "0.2.75-next.3", "private": true, "backstage": { "role": "frontend" }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^1.0.6-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/config": "^1.0.1", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-airbrake": "^0.3.9-next.2", - "@backstage/plugin-apache-airflow": "^0.2.2-next.2", - "@backstage/plugin-api-docs": "^0.8.9-next.2", - "@backstage/plugin-azure-devops": "^0.2.0-next.2", - "@backstage/plugin-badges": "^0.2.33-next.2", + "@backstage/app-defaults": "^1.0.6-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-airbrake": "^0.3.9-next.3", + "@backstage/plugin-apache-airflow": "^0.2.2-next.3", + "@backstage/plugin-api-docs": "^0.8.9-next.3", + "@backstage/plugin-azure-devops": "^0.2.0-next.3", + "@backstage/plugin-badges": "^0.2.33-next.3", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-catalog-graph": "^0.2.21-next.1", - "@backstage/plugin-catalog-import": "^0.8.12-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-circleci": "^0.3.9-next.2", - "@backstage/plugin-cloudbuild": "^0.3.9-next.2", - "@backstage/plugin-code-coverage": "^0.2.2-next.2", - "@backstage/plugin-cost-insights": "^0.11.31-next.2", - "@backstage/plugin-dynatrace": "^0.2.0-next.2", - "@backstage/plugin-explore": "^0.3.40-next.2", - "@backstage/plugin-gcalendar": "^0.3.5-next.2", - "@backstage/plugin-gcp-projects": "^0.3.28-next.2", - "@backstage/plugin-github-actions": "^0.5.9-next.2", - "@backstage/plugin-gocd": "^0.1.15-next.1", - "@backstage/plugin-graphiql": "^0.2.41-next.2", - "@backstage/plugin-home": "^0.4.25-next.2", - "@backstage/plugin-jenkins": "^0.7.8-next.2", - "@backstage/plugin-kafka": "^0.3.9-next.2", - "@backstage/plugin-kubernetes": "^0.7.2-next.2", - "@backstage/plugin-lighthouse": "^0.3.9-next.2", - "@backstage/plugin-newrelic": "^0.3.27-next.2", - "@backstage/plugin-newrelic-dashboard": "^0.2.2-next.1", - "@backstage/plugin-org": "^0.5.9-next.2", - "@backstage/plugin-pagerduty": "0.5.2-next.2", - "@backstage/plugin-permission-react": "^0.4.5-next.1", - "@backstage/plugin-rollbar": "^0.4.9-next.2", - "@backstage/plugin-scaffolder": "^1.6.0-next.2", - "@backstage/plugin-search": "^1.0.2-next.2", + "@backstage/plugin-catalog-graph": "^0.2.21-next.2", + "@backstage/plugin-catalog-import": "^0.8.12-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-circleci": "^0.3.9-next.3", + "@backstage/plugin-cloudbuild": "^0.3.9-next.3", + "@backstage/plugin-code-coverage": "^0.2.2-next.3", + "@backstage/plugin-cost-insights": "^0.11.31-next.3", + "@backstage/plugin-dynatrace": "^0.2.0-next.3", + "@backstage/plugin-explore": "^0.3.40-next.3", + "@backstage/plugin-gcalendar": "^0.3.5-next.3", + "@backstage/plugin-gcp-projects": "^0.3.28-next.3", + "@backstage/plugin-github-actions": "^0.5.9-next.3", + "@backstage/plugin-gocd": "^0.1.15-next.2", + "@backstage/plugin-graphiql": "^0.2.41-next.3", + "@backstage/plugin-home": "^0.4.25-next.3", + "@backstage/plugin-jenkins": "^0.7.8-next.3", + "@backstage/plugin-kafka": "^0.3.9-next.3", + "@backstage/plugin-kubernetes": "^0.7.2-next.3", + "@backstage/plugin-lighthouse": "^0.3.9-next.3", + "@backstage/plugin-newrelic": "^0.3.27-next.3", + "@backstage/plugin-newrelic-dashboard": "^0.2.2-next.2", + "@backstage/plugin-org": "^0.5.9-next.3", + "@backstage/plugin-pagerduty": "0.5.2-next.3", + "@backstage/plugin-permission-react": "^0.4.5-next.2", + "@backstage/plugin-rollbar": "^0.4.9-next.3", + "@backstage/plugin-scaffolder": "^1.6.0-next.3", + "@backstage/plugin-search": "^1.0.2-next.3", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/plugin-search-react": "^1.1.0-next.2", - "@backstage/plugin-sentry": "^0.4.2-next.2", - "@backstage/plugin-shortcuts": "^0.3.1-next.2", - "@backstage/plugin-stack-overflow": "^0.1.5-next.2", - "@backstage/plugin-tech-insights": "^0.3.0-next.2", - "@backstage/plugin-tech-radar": "^0.5.16-next.2", - "@backstage/plugin-techdocs": "^1.3.2-next.2", - "@backstage/plugin-techdocs-module-addons-contrib": "^1.0.4-next.1", - "@backstage/plugin-techdocs-react": "^1.0.4-next.1", - "@backstage/plugin-todo": "^0.2.11-next.2", - "@backstage/plugin-user-settings": "^0.4.8-next.2", + "@backstage/plugin-sentry": "^0.4.2-next.3", + "@backstage/plugin-shortcuts": "^0.3.1-next.3", + "@backstage/plugin-stack-overflow": "^0.1.5-next.3", + "@backstage/plugin-tech-insights": "^0.3.0-next.3", + "@backstage/plugin-tech-radar": "^0.5.16-next.3", + "@backstage/plugin-techdocs": "^1.3.2-next.3", + "@backstage/plugin-techdocs-module-addons-contrib": "^1.0.4-next.2", + "@backstage/plugin-techdocs-react": "^1.0.4-next.2", + "@backstage/plugin-todo": "^0.2.11-next.3", + "@backstage/plugin-user-settings": "^0.4.8-next.3", "@backstage/theme": "^0.2.16", "@internal/plugin-catalog-customized": "0.0.2-next.0", "@material-ui/core": "^4.12.2", @@ -80,7 +80,7 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@rjsf/core": "^3.2.1", "@testing-library/cypress": "^8.0.2", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 635dad30d0..a9ab990f92 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/backend-app-api +## 0.2.1-next.2 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- 409ed984e8: Updated service implementations and backend wiring to support scoped service. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-permission-node@0.6.5-next.3 + ## 0.2.1-next.1 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index d4379bcde6..a028af090f 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.2.1-next.1", + "version": "0.2.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -33,17 +33,17 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-permission-node": "^0.6.5-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-permission-node": "^0.6.5-next.3", "express": "^4.17.1", "express-promise-router": "^4.1.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 87f95aa12a..aaa90ac704 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-common +## 0.15.1-next.3 + +### Patch Changes + +- 96689fbdcb: Workaround for a rare race condition in tests. +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + ## 0.15.1-next.2 ### Patch Changes diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 5509adb752..81dc37caca 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.15.1-next.2", + "version": "0.15.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -34,11 +34,11 @@ "test:kubernetes": "backstage-cli package test -t KubernetesContainerRunner --no-watch" }, "dependencies": { - "@backstage/cli-common": "^0.1.9", - "@backstage/config": "^1.0.1", - "@backstage/config-loader": "^1.1.4-next.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/cli-common": "^0.1.10-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/config-loader": "^1.1.4-next.2", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/types": "^1.0.0", "@google-cloud/storage": "^6.0.0", "@keyv/redis": "^2.2.3", @@ -94,8 +94,8 @@ } }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/archiver": "^5.1.0", "@types/base64-stream": "^1.0.2", "@types/compression": "^1.7.0", diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index e91d4880c6..9684395ce0 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-defaults +## 0.1.1-next.1 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/backend-app-api@0.2.1-next.2 + ## 0.1.1-next.0 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 9485091f76..e754b74c4d 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.1.1-next.0", + "version": "0.1.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -32,11 +32,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-app-api": "^0.2.1-next.0", - "@backstage/backend-plugin-api": "^0.1.2-next.0" + "@backstage/backend-app-api": "^0.2.1-next.2", + "@backstage/backend-plugin-api": "^0.1.2-next.2" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 9bb9cbcc49..b0dadbf61c 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-plugin-api +## 0.1.2-next.2 + +### Patch Changes + +- 409ed984e8: Service are now scoped to either `'plugin'` or `'root'` scope. Service factories have been updated to provide dependency instances directly rather than factory functions. +- 854ba37357: The `createServiceFactory` method has been updated to return a higher-order factory that can accept options. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.2-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 8510f2eaa8..e9593dec3d 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -33,17 +33,17 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/config": "^1.0.1", - "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "winston": "^3.2.1", "winston-transport": "^4.5.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 28017cf3d5..2307fd5d57 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/backend-tasks +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.3.5-next.0 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 7d244a387c..444616660a 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.3.5-next.0", + "version": "0.3.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -32,9 +32,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/types": "^1.0.0", "@types/luxon": "^3.0.0", "cron": "^2.0.0", @@ -47,8 +47,8 @@ "zod": "^3.9.5" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.1", - "@backstage/cli": "^0.19.0-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/cron": "^2.0.0", "wait-for-expect": "^3.0.2" }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index ef8fdeaeec..5ec06645b0 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/backend-test-utils +## 0.1.28-next.3 + +### Patch Changes + +- 854ba37357: Updated to support new `ServiceFactory` formats. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-app-api@0.2.1-next.2 + - @backstage/cli@0.19.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.28-next.2 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 5e421b4b38..374860a387 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.1.28-next.2", + "version": "0.1.28-next.3", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -34,11 +34,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-app-api": "^0.2.1-next.1", - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-app-api": "^0.2.1-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/config": "^1.0.2-next.0", "better-sqlite3": "^7.5.0", "knex": "^2.0.0", "msw": "^0.47.0", @@ -48,7 +48,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 43d4c1c7c2..7b20372856 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,45 @@ # example-backend +## 0.2.75-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.4-next.1 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/plugin-auth-backend@0.16.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + - @backstage/plugin-badges-backend@0.1.30-next.1 + - @backstage/plugin-code-coverage-backend@0.2.2-next.2 + - @backstage/plugin-jenkins-backend@0.1.26-next.3 + - @backstage/plugin-kubernetes-backend@0.7.2-next.3 + - @backstage/plugin-tech-insights-backend@0.5.2-next.2 + - @backstage/plugin-techdocs-backend@1.3.0-next.2 + - @backstage/plugin-todo-backend@0.1.33-next.2 + - example-app@0.2.75-next.3 + - @backstage/plugin-kafka-backend@0.2.29-next.1 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-app-backend@0.3.36-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-azure-devops-backend@0.3.15-next.2 + - @backstage/plugin-graphql-backend@0.1.26-next.3 + - @backstage/plugin-permission-backend@0.5.11-next.2 + - @backstage/plugin-permission-node@0.6.5-next.3 + - @backstage/plugin-proxy-backend@0.2.30-next.2 + - @backstage/plugin-rollbar-backend@0.1.33-next.3 + - @backstage/plugin-search-backend@1.0.2-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.0.2-next.2 + - @backstage/plugin-search-backend-module-pg@0.4.0-next.2 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.20-next.1 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + ## 0.2.75-next.2 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 5518b9d586..a8ae29ee18 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.75-next.2", + "version": "0.2.75-next.3", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,40 +26,40 @@ "build-image": "docker build ../.. -f Dockerfile --tag example-backend" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-app-backend": "^0.3.36-next.2", - "@backstage/plugin-auth-backend": "^0.16.0-next.2", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-azure-devops-backend": "^0.3.15-next.1", - "@backstage/plugin-badges-backend": "^0.1.30-next.0", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", - "@backstage/plugin-code-coverage-backend": "^0.2.2-next.1", - "@backstage/plugin-graphql-backend": "^0.1.26-next.2", - "@backstage/plugin-jenkins-backend": "^0.1.26-next.2", - "@backstage/plugin-kafka-backend": "^0.2.29-next.0", - "@backstage/plugin-kubernetes-backend": "^0.7.2-next.2", - "@backstage/plugin-permission-backend": "^0.5.11-next.1", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-node": "^0.6.5-next.2", - "@backstage/plugin-proxy-backend": "^0.2.30-next.1", - "@backstage/plugin-rollbar-backend": "^0.1.33-next.2", - "@backstage/plugin-scaffolder-backend": "^1.6.0-next.2", - "@backstage/plugin-scaffolder-backend-module-rails": "^0.4.4-next.0", - "@backstage/plugin-search-backend": "^1.0.2-next.0", - "@backstage/plugin-search-backend-module-elasticsearch": "^1.0.2-next.1", - "@backstage/plugin-search-backend-module-pg": "^0.4.0-next.1", - "@backstage/plugin-search-backend-node": "^1.0.2-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-app-backend": "^0.3.36-next.3", + "@backstage/plugin-auth-backend": "^0.16.0-next.3", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-azure-devops-backend": "^0.3.15-next.2", + "@backstage/plugin-badges-backend": "^0.1.30-next.1", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", + "@backstage/plugin-code-coverage-backend": "^0.2.2-next.2", + "@backstage/plugin-graphql-backend": "^0.1.26-next.3", + "@backstage/plugin-jenkins-backend": "^0.1.26-next.3", + "@backstage/plugin-kafka-backend": "^0.2.29-next.1", + "@backstage/plugin-kubernetes-backend": "^0.7.2-next.3", + "@backstage/plugin-permission-backend": "^0.5.11-next.2", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-node": "^0.6.5-next.3", + "@backstage/plugin-proxy-backend": "^0.2.30-next.2", + "@backstage/plugin-rollbar-backend": "^0.1.33-next.3", + "@backstage/plugin-scaffolder-backend": "^1.6.0-next.3", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.4.4-next.1", + "@backstage/plugin-search-backend": "^1.0.2-next.1", + "@backstage/plugin-search-backend-module-elasticsearch": "^1.0.2-next.2", + "@backstage/plugin-search-backend-module-pg": "^0.4.0-next.2", + "@backstage/plugin-search-backend-node": "^1.0.2-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", - "@backstage/plugin-tech-insights-backend": "^0.5.2-next.1", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.20-next.0", - "@backstage/plugin-tech-insights-node": "^0.3.4-next.0", - "@backstage/plugin-techdocs-backend": "^1.3.0-next.1", - "@backstage/plugin-todo-backend": "^0.1.33-next.1", + "@backstage/plugin-tech-insights-backend": "^0.5.2-next.2", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "^0.1.20-next.1", + "@backstage/plugin-tech-insights-node": "^0.3.4-next.1", + "@backstage/plugin-techdocs-backend": "^1.3.0-next.2", + "@backstage/plugin-todo-backend": "^0.1.33-next.2", "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^19.0.3", "azure-devops-node-api": "^11.0.1", @@ -76,7 +76,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/dockerode": "^3.3.0", "@types/express": "^4.17.6", "@types/express-serve-static-core": "^4.17.5", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 77e0b7ab48..6cbcab0a4e 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/catalog-client +## 1.1.0-next.2 + +### Minor Changes + +- 65d1d4343f: Adding `validateEntity` method that calls `/validate-entity` endpoint. + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/errors@1.1.1-next.0 + ## 1.0.5-next.1 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 61d47aa65e..3a06074a4d 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.0.5-next.1", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/errors": "^1.1.0", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/errors": "^1.1.1-next.0", "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "msw": "^0.47.0" }, "files": [ diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 9554b94788..25d5866002 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/catalog-model +## 1.1.1-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + ## 1.1.0 ### Minor Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index be2cbb7664..28df6e58fc 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.1.0", + "version": "1.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/types": "^1.0.0", "ajv": "^8.10.0", "json-schema": "^0.4.0", @@ -42,7 +42,7 @@ "uuid": "^8.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/json-schema": "^7.0.5", "@types/lodash": "^4.14.151", "yaml": "^2.0.0" diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index b5b24d099e..05362b7a31 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli-common +## 0.1.10-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + ## 0.1.9 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index e95a07d401..965c62ce38 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.9", + "version": "0.1.10-next.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -32,7 +32,7 @@ "start": "backstage-cli package start" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/node": "^16.0.0" }, "files": [ diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 6d40a22cae..52ba0a24c6 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/cli +## 0.19.0-next.3 + +### Patch Changes + +- 7d47def9c4: Added dependency on `@types/jest` v27. The `@types/jest` dependency has also been removed from the plugin template and should be removed from any of your own internal packages. If you wish to override the version of `@types/jest` or `jest`, use Yarn resolutions. +- a7e82c9b01: Updated `versions:bump` command to be compatible with Yarn 3. +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/release-manifests@0.0.6-next.2 + ## 0.19.0-next.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index f267a0d9ad..9a412d401f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.19.0-next.2", + "version": "0.19.0-next.3", "publishConfig": { "access": "public" }, @@ -30,11 +30,11 @@ "backstage-cli": "bin/backstage-cli" }, "dependencies": { - "@backstage/cli-common": "^0.1.9", - "@backstage/config": "^1.0.1", - "@backstage/config-loader": "^1.1.4-next.1", - "@backstage/errors": "^1.1.0", - "@backstage/release-manifests": "^0.0.6-next.1", + "@backstage/cli-common": "^0.1.10-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/config-loader": "^1.1.4-next.2", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/release-manifests": "^0.0.6-next.2", "@backstage/types": "^1.0.0", "@manypkg/get-packages": "^1.1.3", "@octokit/request": "^6.0.0", @@ -129,13 +129,13 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@types/diff": "^5.0.0", "@types/express": "^4.17.6", diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index ab9ddbc28c..43b2bb2d8a 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/codemods +## 0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + ## 0.1.38 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 69720ab0a2..c7630cae6f 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.38", + "version": "0.1.39-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" @@ -33,13 +33,13 @@ "backstage-codemods": "bin/backstage-codemods" }, "dependencies": { - "@backstage/cli-common": "^0.1.9", + "@backstage/cli-common": "^0.1.10-next.0", "chalk": "^4.0.0", "jscodeshift": "^0.13.0", "jscodeshift-add-imports": "^1.0.10" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/jscodeshift": "^0.11.0", "@types/node": "^16.11.26", "commander": "^9.1.0", diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 8e49a132ce..c46763bccd 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/config-loader +## 1.1.4-next.2 + +### Patch Changes + +- 5ecca7e44b: No longer log when reloading remote config. +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + ## 1.1.4-next.1 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 95704de6f3..3f0644e3d6 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "1.1.4-next.1", + "version": "1.1.4-next.2", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -33,9 +33,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/cli-common": "^0.1.9", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/cli-common": "^0.1.10-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/types": "^1.0.0", "@types/json-schema": "^7.0.6", "ajv": "^8.10.0", @@ -50,7 +50,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/json-schema-merge-allof": "^0.6.0", "@types/mock-fs": "^4.10.0", "@types/node": "^16.11.26", diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 7858e99096..9b9ea96dd1 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/config +## 1.0.2-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + ## 1.0.1 ### Patch Changes diff --git a/packages/config/package.json b/packages/config/package.json index ff759170bd..9610495455 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "1.0.1", + "version": "1.0.2-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -36,8 +36,8 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@types/node": "^16.0.0" }, "files": [ diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 6fe94bee7f..47740e9e7b 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/core-app-api +## 1.1.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 1.1.0-next.2 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index c5b8907b8f..8532997477 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.1.0-next.2", + "version": "1.1.0-next.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,8 +32,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", @@ -48,8 +48,8 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index f0ecf302c9..64c5ddc502 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/core-components +## 0.11.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.11.1-next.2 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index e316e7d6f4..a32961eece 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.11.1-next.2", + "version": "0.11.1-next.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,9 +32,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", "@backstage/version-bridge": "^1.0.1", "@material-table/core": "^3.1.0", @@ -78,9 +78,9 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index a1da7291e9..0889d0d6e9 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/core-plugin-api +## 1.0.6-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + ## 1.0.6-next.2 ### Patch Changes diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index a40ffcf3bb..5d013f6e87 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.0.6-next.2", + "version": "1.0.6-next.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -33,7 +33,7 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1", + "@backstage/config": "^1.0.2-next.0", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "history": "^5.0.0", @@ -46,9 +46,9 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index c30f0c9d75..e131c59b6c 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/create-app +## 0.4.31-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/cli-common@0.1.10-next.0 + ## 0.4.31-next.2 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 6523e36bc0..d059446638 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.4.31-next.2", + "version": "0.4.31-next.3", "publishConfig": { "access": "public" }, @@ -32,7 +32,7 @@ "start": "nodemon --" }, "dependencies": { - "@backstage/cli-common": "^0.1.9", + "@backstage/cli-common": "^0.1.10-next.0", "chalk": "^4.0.0", "commander": "^9.1.0", "fs-extra": "10.1.0", @@ -42,7 +42,7 @@ "recursive-readdir": "^2.2.2" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/fs-extra": "^9.0.1", "@types/inquirer": "^8.1.3", "@types/node": "^16.11.26", diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 6115fc076e..e292fde14c 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/dev-utils +## 1.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 329ed2b9c7: Fixed routing when using React Router v6 stable. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + ## 1.0.6-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 671f264e79..dbbdce225a 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.6-next.1", + "version": "1.0.6-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,14 +32,14 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/app-defaults": "^1.0.6-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-app-api": "^1.1.0-next.1", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/integration-react": "^1.1.4-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/app-defaults": "^1.0.6-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -57,7 +57,7 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/node": "^16.0.0" }, "files": [ diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index b9660518a5..12f430cad2 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -27,9 +27,9 @@ }, "bin": "bin/e2e-test", "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/cli-common": "^0.1.9-next.0", - "@backstage/errors": "^1.1.0-next.0", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/cli-common": "^0.1.10-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/fs-extra": "^9.0.1", "@types/node": "^16.11.26", "@types/puppeteer": "^5.4.4", diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index bb3eba0249..cbb5292829 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/errors +## 1.1.1-next.0 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + ## 1.1.0 ### Minor Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index 3a84d4c7c5..ab315338bb 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "1.1.0", + "version": "1.1.1-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -37,7 +37,7 @@ "serialize-error": "^8.0.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 41afc53fe8..f09758bffe 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/integration-react +## 1.1.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + ## 1.1.4-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 34e50cf84b..80ea2f029b 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.4-next.1", + "version": "1.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration": "^1.3.1-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -37,9 +37,9 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index ac5ec94bc4..0ac5e9e5bd 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/integration +## 1.3.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- f76f22c649: Improved caching around github app tokens. + Tokens are now cached for 50 minutes, not 10. + Calls to get app installations are also included in this cache. + If you have more than one github app configured, consider adding `allowedInstallationOwners` to your apps configuration to gain the most benefit from these performance changes. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + ## 1.3.1-next.1 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index ba6ef42fb2..c68bd3176c 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "1.3.1-next.1", + "version": "1.3.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@octokit/auth-app": "^4.0.0", "@octokit/rest": "^19.0.3", "cross-fetch": "^3.1.5", @@ -42,9 +42,9 @@ "luxon": "^3.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/config-loader": "^1.1.4-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/config-loader": "^1.1.4-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@types/luxon": "^3.0.0", "msw": "^0.47.0" }, diff --git a/packages/release-manifests/CHANGELOG.md b/packages/release-manifests/CHANGELOG.md index 2445088982..b0e104511f 100644 --- a/packages/release-manifests/CHANGELOG.md +++ b/packages/release-manifests/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/release-manifests +## 0.0.6-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. + ## 0.0.6-next.1 ### Patch Changes diff --git a/packages/release-manifests/package.json b/packages/release-manifests/package.json index 371745f43f..44c081581c 100644 --- a/packages/release-manifests/package.json +++ b/packages/release-manifests/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/release-manifests", "description": "Helper library for receiving release manifests", - "version": "0.0.6-next.1", + "version": "0.0.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -35,8 +35,8 @@ "cross-fetch": "^3.1.5" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@types/node": "^16.0.0", "msw": "^0.47.0" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 55552f363e..ee1e3ea184 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,23 @@ # techdocs-cli-embedded-app +## 0.2.74-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/app-defaults@1.0.6-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/cli@0.19.0-next.3 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + ## 0.2.74-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 295688eca8..a8d0e0cf4c 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,24 +1,24 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.74-next.1", + "version": "0.2.74-next.2", "private": true, "backstage": { "role": "frontend" }, "bundled": true, "dependencies": { - "@backstage/app-defaults": "^1.0.6-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/cli": "^0.19.0-next.1", - "@backstage/config": "^1.0.1", - "@backstage/core-app-api": "^1.1.0-next.1", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/integration-react": "^1.1.4-next.0", - "@backstage/plugin-catalog": "^1.5.1-next.1", - "@backstage/plugin-techdocs": "^1.3.2-next.1", - "@backstage/plugin-techdocs-react": "^1.0.4-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/app-defaults": "^1.0.6-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog": "^1.5.1-next.3", + "@backstage/plugin-techdocs": "^1.3.2-next.3", + "@backstage/plugin-techdocs-react": "^1.0.4-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -30,7 +30,7 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index 17780a3887..56fdf6afd2 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,17 @@ # @techdocs/cli +## 1.2.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/cli-common@0.1.10-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-techdocs-node@1.4.0-next.2 + ## 1.2.1-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 97d8a5e721..2ec384eb34 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.2.1-next.1", + "version": "1.2.1-next.2", "publishConfig": { "access": "public" }, @@ -36,7 +36,7 @@ "techdocs-cli": "bin/techdocs-cli" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/commander": "^2.12.2", "@types/fs-extra": "^9.0.6", "@types/http-proxy": "^1.17.4", @@ -60,11 +60,11 @@ "ext": "ts" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-model": "^1.1.0", - "@backstage/cli-common": "^0.1.9", - "@backstage/config": "^1.0.1", - "@backstage/plugin-techdocs-node": "^1.4.0-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/cli-common": "^0.1.10-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-techdocs-node": "^1.4.0-next.2", "@types/dockerode": "^3.3.0", "commander": "^9.1.0", "dockerode": "^3.3.1", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 2317386cf7..b4101d9514 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/test-utils +## 1.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- d9e39544be: Add missing peer dependencies +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + ## 1.2.0-next.2 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 8399e09357..4d45519fa1 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.2.0-next.2", + "version": "1.2.0-next.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,11 +32,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-react": "^0.4.5-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-react": "^0.4.5-next.2", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", @@ -55,7 +55,7 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/node": "^16.11.26", "msw": "^0.47.0" }, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index 9b5bdf0ebd..b92a33a8f0 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-adr-backend +## 0.2.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-adr-common@0.2.1-next.1 + ## 0.2.1-next.2 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 2ebdd9c78f..91ed8e002c 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.2.1-next.2", + "version": "0.2.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,13 +28,13 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-adr-common": "^0.2.1-next.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-adr-common": "^0.2.1-next.1", "@backstage/plugin-search-common": "^1.0.1-next.0", "luxon": "^3.0.0", "marked": "^4.0.14", @@ -43,7 +43,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/marked": "^4.0.0", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 63584b41b1..9269768185 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-adr-common +## 0.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + ## 0.2.1-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index c5a49f59fe..02631c3e6c 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.1-next.0", + "version": "0.2.1-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/integration": "^1.3.1-next.0", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index 494a7f33fe..3fc5634bd1 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-adr +## 0.2.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-adr-common@0.2.1-next.1 + ## 0.2.1-next.2 ### Patch Changes diff --git a/plugins/adr/package.json b/plugins/adr/package.json index db9ba4a11c..732cb4d67f 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.2.1-next.2", + "version": "0.2.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-adr-common": "^0.2.1-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-adr-common": "^0.2.1-next.1", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/plugin-search-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.16", @@ -45,10 +45,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index d6c30dddcb..1868062e0b 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-airbrake-backend +## 0.2.9-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.9-next.2 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 3a658af4e3..1a04e5185d 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.2.9-next.2", + "version": "0.2.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", "@types/express": "*", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -32,7 +32,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 6935373985..8262a89cb0 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-airbrake +## 0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/dev-utils@1.0.6-next.2 + - @backstage/test-utils@1.2.0-next.3 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 3d829c4bd0..c8ec322420 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -40,10 +40,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/app-defaults": "^1.0.6-next.1", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/app-defaults": "^1.0.6-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index f7db453135..64e114dda7 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-allure +## 0.1.25-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.25-next.2 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 511b3b02a5..12400806a7 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.25-next.2", + "version": "0.1.25-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -38,10 +38,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 0e666be80a..fb5051da23 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-analytics-module-ga +## 0.1.20-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.20-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index a10056153b..e9b5044d92 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.20-next.1", + "version": "0.1.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -36,10 +36,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 3f3f236b76..2396ca2b6f 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apache-airflow +## 0.2.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.2.2-next.2 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 5cf15f7620..f132c46a78 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.2-next.2", + "version": "0.2.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +35,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index d71021782f..db0ffbeada 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-api-docs +## 0.8.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + ## 0.8.9-next.2 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 1ae1c8e00f..8281a1522d 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.8.9-next.2", + "version": "0.8.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ }, "dependencies": { "@asyncapi/react-component": "1.0.0-next.40", - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog": "^1.5.1-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog": "^1.5.1-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -56,10 +56,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 68983a1f07..40c9fa0c57 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-apollo-explorer +## 0.1.2-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index b33901b96f..39143c3133 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,8 +23,8 @@ }, "dependencies": { "@apollo/explorer": "^1.1.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -36,10 +36,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 33df9f7078..02188afefc 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-app-backend +## 0.3.36-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.1.4-next.2 + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.3.36-next.2 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index f37e9e5ab8..c06c41e6dd 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.36-next.2", + "version": "0.3.36-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/config-loader": "^1.1.4-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/config-loader": "^1.1.4-next.2", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -49,8 +49,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@backstage/types": "^1.0.0", "@types/supertest": "^2.0.8", "mock-fs": "^5.1.0", diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 7b723756cf..7c5fff0dd0 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend +## 0.16.0-next.3 + +### Minor Changes + +- 8600855fbf: The auth0 integration is updated to use the `passport-auth0` library. The configuration under `auth.providers.auth0.\*` now supports an optional `audience` parameter; providing that allows you to connect to the correct API to get permissions, access tokens, and full profile information. + + [What is an Audience](https://community.auth0.com/t/what-is-the-audience/71414) + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 0.16.0-next.2 ### Patch Changes diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 35e6f86f2c..4f820f4829 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.16.0-next.2", + "version": "0.16.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", "@backstage/types": "^1.0.0", "@davidzemon/passport-okta-oauth": "^0.0.5", "@google-cloud/firestore": "^6.0.0", @@ -76,8 +76,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/body-parser": "^1.19.0", "@types/cookie-parser": "^1.4.2", "@types/express-session": "^1.17.2", diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 71413dc6ef..13fb0bbcce 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-auth-node +## 0.2.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.5-next.2 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index ebf8c6974d..52115d6611 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.2.5-next.2", + "version": "0.2.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/express": "*", "express": "^4.17.1", "jose": "^4.6.0", @@ -32,8 +32,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "lodash": "^4.17.21", "msw": "^0.47.0", "uuid": "^8.0.0" diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index dba2ff571a..d6145f3308 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-azure-devops-backend +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index debcf701e2..92bcf84c62 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.3.15-next.1", + "version": "0.3.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,8 +22,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", "@backstage/plugin-azure-devops-common": "^0.3.0-next.0", "@types/express": "^4.17.6", "azure-devops-node-api": "^11.0.1", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.6" diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index e4fa40551a..13ea5bbaa5 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-azure-devops +## 0.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.0-next.2 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 969103db00..0cdd048b1b 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.2.0-next.2", + "version": "0.2.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,12 +28,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/plugin-azure-devops-common": "^0.3.0-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index f26dab77f3..c54c09a08b 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-badges-backend +## 0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.30-next.0 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 420bfbd86b..0002695cc8 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.1.30-next.0", + "version": "0.1.30-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/catalog-client": "^1.0.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/express": "^4.17.6", "badge-maker": "^3.3.0", "cors": "^2.8.5", @@ -47,7 +47,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 0533b306d1..50137c221b 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-badges +## 0.2.33-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.33-next.2 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 100f2a6102..8748a05077 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.33-next.2", + "version": "0.2.33-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,11 +29,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index b6cec7bc0d..4494697278 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-bazaar-backend +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-test-utils@0.1.28-next.3 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 0c7c2c51ea..c1242acd7e 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.1.20-next.0", + "version": "0.1.20-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/backend-test-utils": "^0.1.28-next.1", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/config": "^1.0.2-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -33,7 +33,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index c8fbcb961b..8d93b89e0f 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-bazaar +## 0.1.24-next.2 + +### Patch Changes + +- 1dd12349d1: Fixed broken routing by removing the wrapping `Router` from the `RoutedTabs` children. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/cli@0.19.0-next.3 + ## 0.1.24-next.1 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index f78a4f08fe..21e2f3ce25 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.1.24-next.1", + "version": "0.1.24-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,13 +22,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/cli": "^0.19.0-next.1", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-catalog": "^1.5.1-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog": "^1.5.1-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -44,8 +44,8 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/dev-utils": "^1.0.6-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", "@testing-library/jest-dom": "^5.10.1", "cross-fetch": "^3.1.5" }, diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index f940cb40df..114ab5549e 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-bitrise +## 0.1.36-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.36-next.2 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index a849fba8ef..b659cac03a 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.36-next.2", + "version": "0.1.36-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 10196c0793..07b5446dcc 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 871f32773b..33158ac182 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.1.9-next.1", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,13 +32,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.0", - "@backstage/plugin-catalog-backend": "^1.4.0-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@backstage/types": "^1.0.0", "aws-sdk": "^2.840.0", "lodash": "^4.17.21", @@ -47,7 +47,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151", "aws-sdk-mock": "^5.2.1", "yaml": "^2.0.0" diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index de79e9f47c..57d5315cf4 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 2c7ab06064..3dd90d1bb3 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.7-next.2", + "version": "0.1.7-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,13 +32,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", "msw": "^0.47.0", @@ -47,8 +47,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index b75a810816..cd50519279 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 441e7c5ab2..e8ddff85b0 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.3-next.2", + "version": "0.1.3-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,18 +32,18 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-bitbucket-cloud-common": "^0.1.3-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "msw": "^0.47.0" }, "files": [ diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 7a8b1c95bc..ae82dc8ad7 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.1-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.1-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 31b24687e8..4064732eca 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.1-next.2", + "version": "0.1.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,21 +31,21 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.0.1", - "@backstage/config": "^1.0.0", - "@backstage/errors": "^1.0.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@types/node-fetch": "^2.5.12", "node-fetch": "^2.6.7", "uuid": "^8.0.0", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "msw": "^0.47.0" }, "files": [ diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 65f5fb11f1..7533ebaa47 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.3-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.3-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 7881402dea..7d27598d1f 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.3-next.2", + "version": "0.2.3-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,13 +32,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-bitbucket-cloud-common": "^0.1.3-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", "msw": "^0.47.0", @@ -46,8 +46,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index 015804e6ea..d90cbfbe10 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.4-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index af98288b4e..53d54afc06 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.4-next.2", + "version": "0.1.4-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,13 +28,13 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "fs-extra": "10.1.0", "msw": "^0.47.0", "node-fetch": "^2.6.7", @@ -42,8 +42,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/fs-extra": "^9.0.1" }, "files": [ diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index aa8db8962d..a1a11f1519 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-backend-module-github +## 0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 04a4d3c01f..c27d3d4c60 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.1.7-next.2", + "version": "0.1.7-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,15 +33,15 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", - "@backstage/plugin-catalog-node": "^1.0.2-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", + "@backstage/plugin-catalog-node": "^1.1.0-next.2", "@backstage/types": "^1.0.0", "@octokit/graphql": "^5.0.0", "lodash": "^4.17.21", @@ -51,8 +51,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 958fce089d..ba2016b713 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 9933f8c5a8..56d6fd73e8 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.1.7-next.2", + "version": "0.1.7-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,13 +32,13 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@backstage/types": "^1.0.0", "lodash": "^4.17.21", "msw": "^0.47.0", @@ -47,8 +47,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151", "@types/uuid": "^8.0.0" }, diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index addb85f704..6429576b05 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.5.3-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 35924aaf67..4d9de73a77 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.3-next.1", + "version": "0.5.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-backend": "^1.4.0-next.1", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@backstage/types": "^1.0.0", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", @@ -45,7 +45,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index e69fa287c9..25ac8c2716 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.4.2-next.3 + +### Patch Changes + +- d80aab31ae: Added $select attribute to user query +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.4.2-next.2 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 3bddab4130..93270570fb 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.4.2-next.2", + "version": "0.4.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ }, "dependencies": { "@azure/identity": "^2.1.0", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", "@microsoft/microsoft-graph-types": "^2.6.0", "@types/node-fetch": "^2.5.12", "lodash": "^4.17.21", @@ -47,9 +47,9 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151", "msw": "^0.47.0" }, diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index e93151d472..f9a1ad9ed9 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 55ffe05fc7..420a9d547e 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.2-next.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,19 +33,19 @@ }, "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/integration": "^1.3.1-next.0", - "@backstage/plugin-catalog-backend": "^1.4.0-next.1", - "@backstage/plugin-catalog-node": "^1.0.2-next.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", + "@backstage/plugin-catalog-node": "^1.1.0-next.2", "@backstage/types": "^1.0.0", "winston": "^3.2.1", "yaml": "^2.1.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.1", - "@backstage/cli": "^0.19.0-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "openapi-types": "^12.0.0" }, "files": [ diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 7fb1cf7cab..07d434b7b2 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-catalog-backend +## 1.4.0-next.3 + +### Minor Changes + +- 6e63bc43f2: Added the `refresh` function to the Connection of the entity providers. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + - @backstage/plugin-permission-node@0.6.5-next.3 + ## 1.4.0-next.2 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index fe0478e115..0b9d363b3a 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.4.0-next.2", + "version": "1.4.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,18 +33,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-catalog-node": "^1.0.2-next.1", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-node": "^0.6.5-next.2", - "@backstage/plugin-scaffolder-common": "^1.2.0-next.0", + "@backstage/plugin-catalog-node": "^1.1.0-next.2", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-node": "^0.6.5-next.3", + "@backstage/plugin-scaffolder-common": "^1.2.0-next.1", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", @@ -69,10 +69,10 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-search-backend-node": "1.0.2-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-search-backend-node": "1.0.2-next.2", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 7d11622796..5fbaa9ecca 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-catalog-graph +## 0.2.21-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.2.21-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 3f9a79ee9a..995ed3eebe 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.21-next.1", + "version": "0.2.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,11 +22,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,11 +43,11 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/core-app-api": "^1.1.0-next.1", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/plugin-catalog": "^1.5.1-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/plugin-catalog": "^1.5.1-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/types": "^1.0.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index 53e66ef2c7..28eafef43b 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-graphql +## 0.3.13-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + ## 0.3.13-next.2 ### Patch Changes diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index d4268ea270..b8c65b2784 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", "description": "An experimental Backstage catalog GraphQL module", - "version": "0.3.13-next.2", + "version": "0.3.13-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,8 +34,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", "@backstage/types": "^1.0.0", "apollo-server": "^3.0.0", "graphql": "^16.0.0", @@ -46,8 +46,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@graphql-codegen/cli": "^2.3.1", "@graphql-codegen/graphql-modules-preset": "^2.3.2", "@graphql-codegen/typescript": "^2.4.2", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index c817f09e8d..35633dca6a 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-import +## 0.8.12-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + ## 0.8.12-next.2 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 9d6a6945e0..895973f1ca 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.8.12-next.2", + "version": "0.8.12-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,15 +32,15 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -58,10 +58,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 24006068f6..0c88527b97 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-catalog-node +## 1.1.0-next.2 + +### Minor Changes + +- 9743bc788c: Added refresh function to the `EntityProviderConnection` to be able to schedule refreshes from entity providers. + +### Patch Changes + +- 409ed984e8: Updated usage of experimental backend service APIs. +- Updated dependencies + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/errors@1.1.1-next.0 + ## 1.0.2-next.1 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 991aa67b68..2ef9a738fc 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.0.2-next.1", + "version": "1.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,16 +24,16 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/errors": "1.1.0", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/errors": "1.1.1-next.0", "@backstage/types": "^1.0.0" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2" + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 59a178de9e..a0e7bfcae5 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-react +## 1.1.4-next.2 + +### Patch Changes + +- f6033d1121: humanizeEntityRef function can now be forced to include default namespace +- c86741a052: Support showing counts in option labels of the `EntityTagPicker`. You can enable this by adding the `showCounts` property +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + ## 1.1.4-next.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c7c17f9b2f..962c859c62 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.1.4-next.1", + "version": "1.1.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,15 +33,15 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.0", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-permission-common": "^0.6.4-next.0", - "@backstage/plugin-permission-react": "^0.4.5-next.1", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-react": "^0.4.5-next.2", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", @@ -62,11 +62,11 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/core-app-api": "^1.1.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-scaffolder-common": "^1.2.0-next.0", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/plugin-scaffolder-common": "^1.2.0-next.1", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 814f75e80c..51507389cf 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-catalog +## 1.5.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration-react@1.1.4-next.2 + ## 1.5.1-next.2 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index ed0198b799..2610c9db93 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.5.1-next.2", + "version": "1.5.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,14 +32,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration-react": "^1.1.4-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration-react": "^1.1.4-next.2", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/plugin-search-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.16", @@ -59,11 +59,11 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/plugin-permission-react": "^0.4.5-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/plugin-permission-react": "^0.4.5-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 4846df3e12..32ababf2d9 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-cicd-statistics@0.1.11-next.2 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 15d3f5d6b3..ee8eaed465 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,16 +28,16 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-cicd-statistics": "^0.1.11-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-cicd-statistics": "^0.1.11-next.2", "@gitbeaker/browser": "^35.6.0", "@gitbeaker/core": "^35.6.0", "luxon": "^3.0.0", "p-limit": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 1ad30f818b..ac1cd23660 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cicd-statistics +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.11-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 2964a0b6f1..6394baaf94 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.11-next.1", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,14 +32,14 @@ "start": "backstage-cli package start" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/luxon": "^3.0.0", "@types/react": "^16.13.1 || ^17.0.0" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@date-io/luxon": "^1.3.13", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.11.2", diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 82c0ffdba6..44ccf89c42 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-circleci +## 0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 29a4144db4..229ff9fb11 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 2f9cd9b608..35a8a675e0 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cloudbuild +## 0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 1994c6c3fd..6215547041 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 3bc35b9466..3d45e5c3a2 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-code-climate +## 0.1.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.9-next.2 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 83a1787c43..464142f680 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.9-next.2", + "version": "0.1.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,9 +39,9 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 8f788c4614..2d440fd31b 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-code-coverage-backend +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index b74209374f..bbc5714fb8 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,12 +23,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -39,7 +39,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 3b235f5926..9e120afd38 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-code-coverage +## 0.2.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.2-next.2 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 88fb957420..c3f992a428 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.2.2-next.2", + "version": "0.2.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,12 +23,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index b42a2ec80c..aa43d5edd3 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-codescene +## 0.1.4-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.4-next.2 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index 303046610a..bc709a215c 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.4-next.2", + "version": "0.1.4-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.9.10", "@material-ui/icons": "^4.9.1", @@ -38,10 +38,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index d65e0a1cdc..3e7483e879 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-config-schema +## 0.1.32-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.32-next.2 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index f8d3d3e5cf..7f650fb4bc 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.32-next.2", + "version": "0.1.32-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index d0d1b2c76f..fec45acdd1 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-cost-insights +## 0.11.31-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.11.31-next.2 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index 666e4bdbae..8034195d62 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.11.31-next.2", + "version": "0.11.31-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,10 +32,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/plugin-cost-insights-common": "^0.1.1", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", @@ -59,10 +59,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index 4ca38cc5b7..33e547a2bf 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-dynatrace +## 0.2.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.2.0-next.2 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 008e6f116f..3df69ca25f 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "0.2.0-next.2", + "version": "0.2.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -36,10 +36,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index ba33b2f29d..f3bdba1397 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @internal/plugin-todo-list-backend +## 1.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 1.0.5-next.0 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 876afd4ea8..5623c22f58 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.5-next.0", + "version": "1.0.5-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,10 +23,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", "msw": "^0.47.0", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index c61f7049a3..0a1d2c795d 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-explore-react +## 0.0.21-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.0.21-next.2 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 404832050a..1e715965a8 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.21-next.2", + "version": "0.0.21-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-plugin-api": "^1.0.6-next.2" + "@backstage/core-plugin-api": "^1.0.6-next.3" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 84f1f77494..c558be8b63 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-explore +## 0.3.40-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-explore-react@0.0.21-next.3 + ## 0.3.40-next.2 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index c06fcfc709..c0a5453c02 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.3.40-next.2", + "version": "0.3.40-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-explore-react": "^0.0.21-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-explore-react": "^0.0.21-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index e1bea4bf11..1e55a1fdfa 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-firehydrant +## 0.1.26-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.1.26-next.2 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 695f0c60ee..bc10c957c6 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.26-next.2", + "version": "0.1.26-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,9 +23,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -37,10 +37,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 68e6ec5a6e..05ec48b992 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-fossa +## 0.2.41-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.41-next.1 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index f84604135b..c96353f3d6 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.41-next.1", + "version": "0.2.41-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 7f522a6f9f..f87f087880 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-gcalendar +## 0.3.5-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.3.5-next.2 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index d5a5125fd3..fbcc9b0c33 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.5-next.2", + "version": "0.3.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -43,10 +43,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 95d1360c7e..cbd55e8414 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gcp-projects +## 0.3.28-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.28-next.2 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 88f8c2c99f..601d491184 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.28-next.2", + "version": "0.3.28-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -46,10 +46,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 9ca3416e82..1dc0bd72bd 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-git-release-manager +## 0.3.22-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + ## 0.3.22-next.2 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 3b90a363e3..fb56a6d0e1 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.22-next.2", + "version": "0.3.22-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,9 +23,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration": "^1.3.1-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 91fdab23d7..b261cef2ba 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-actions +## 0.5.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + ## 0.5.9-next.2 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 646c599663..7866ded70e 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.5.9-next.2", + "version": "0.5.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -53,10 +53,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index e429e1f325..655d640357 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-github-deployments +## 0.1.40-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + ## 0.1.40-next.2 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 04085204a8..8e32c3c0ff 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.40-next.2", + "version": "0.1.40-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,13 +23,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index e36a2f2af8..758146689a 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-github-issues +## 0.1.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 3cbcb54bca..b98197505c 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.1.1-next.1", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.0.3", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.9.1", @@ -40,10 +40,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@spotify/prettier-config": "^14.0.0", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 8455285ce0..37d3fdc257 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.3-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + ## 0.1.3-next.2 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 03a1bd081e..d667acb5a3 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.3-next.2", + "version": "0.1.3-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,11 +34,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,9 +48,9 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 88cd223f38..93975d7184 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-gitops-profiles +## 0.3.27-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.27-next.2 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 9b850e5dc3..6e54ed98e9 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.27-next.2", + "version": "0.3.27-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -46,10 +46,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 2a9f31f68b..3673cc4163 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-gocd +## 0.1.15-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index cee6976b5b..0ab50a90e5 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.15-next.1", + "version": "0.1.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,11 +29,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 34c80287a7..a9f2f743ec 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.41-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.2.41-next.2 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index e19e1d4036..d6a16708b9 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.41-next.2", + "version": "0.2.41-next.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index 86b91c9329..c94a7619b5 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphql-backend +## 0.1.26-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-catalog-graphql@0.3.13-next.3 + ## 0.1.26-next.2 ### Patch Changes diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index 1f896d9128..96fe0c1fe8 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.26-next.2", + "version": "0.1.26-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,9 +33,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/plugin-catalog-graphql": "^0.3.13-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-catalog-graphql": "^0.3.13-next.3", "@graphql-tools/schema": "^9.0.0", "@types/express": "^4.17.6", "apollo-server": "^3.0.0", @@ -50,7 +50,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 4c5c71d262..55da92f23f 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-home +## 0.4.25-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-stack-overflow@0.1.5-next.3 + ## 0.4.25-next.2 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index c53de70940..df285bad43 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.25-next.2", + "version": "0.4.25-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-stack-overflow": "^0.1.5-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-stack-overflow": "^0.1.5-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 75da9167fe..bfb3ada100 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-ilert +## 0.1.35-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.35-next.2 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index bdf7bdd430..7aa79fb143 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.1.35-next.2", + "version": "0.1.35-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@date-io/luxon": "1.x", "@material-ui/core": "^4.12.2", @@ -42,10 +42,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 90756caa1c..9aa3e20d79 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-jenkins-backend +## 0.1.26-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 0.1.26-next.2 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index d910c9e682..55f856003e 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.1.26-next.2", + "version": "0.1.26-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,14 +24,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", "@backstage/plugin-jenkins-common": "^0.1.8-next.0", - "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -41,7 +41,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 5fc8526590..c6cc5ed432 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-jenkins +## 0.7.8-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.7.8-next.2 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 3243bd6411..f415770809 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.7.8-next.2", + "version": "0.7.8-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-jenkins-common": "^0.1.8-next.0", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", @@ -52,10 +52,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 6dd2737b9a..6bd87b05b7 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kafka-backend +## 0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.29-next.0 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 424c5db9fc..0d65283a53 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.2.29-next.0", + "version": "0.2.29-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -46,7 +46,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/jest-when": "^3.5.0", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 415c7603cd..3a9e86b62e 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-kafka +## 0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 026d26de62..291f1dcea6 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,11 +24,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -40,10 +40,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index f023e16e7d..626003f241 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-kubernetes-backend +## 0.7.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-kubernetes-common@0.4.2-next.1 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 0.7.2-next.2 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 8af7439255..f40492e1b7 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.7.2-next.2", + "version": "0.7.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,13 +35,13 @@ }, "dependencies": { "@azure/identity": "^2.0.4", - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-kubernetes-common": "^0.4.2-next.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-kubernetes-common": "^0.4.2-next.1", "@google-cloud/container": "^4.0.0", "@kubernetes/client-node": "^0.17.0", "@types/express": "^4.17.6", @@ -62,7 +62,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/aws4": "^1.5.1", "aws-sdk-mock": "^5.2.1", "supertest": "^6.1.3" diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 3046aab5d2..08ba0764dc 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-kubernetes-common +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + ## 0.4.2-next.0 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index af5342db3f..3095ac68d4 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.4.2-next.0", + "version": "0.4.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,11 +38,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", + "@backstage/catalog-model": "^1.1.1-next.0", "@kubernetes/client-node": "^0.17.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 29f502d17a..264e550c5c 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-kubernetes +## 0.7.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 19a27929fb: Reset error state on success +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-kubernetes-common@0.4.2-next.1 + ## 0.7.2-next.2 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 574e1aa9fa..27b91b7c79 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.7.2-next.2", + "version": "0.7.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-kubernetes-common": "^0.4.2-next.0", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-kubernetes-common": "^0.4.2-next.1", "@backstage/theme": "^0.2.16", "@kubernetes/client-node": "^0.17.0", "@material-ui/core": "^4.12.2", @@ -56,10 +56,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 4c2bf73400..7cb872e30f 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-lighthouse +## 0.3.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.9-next.2 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index d209f4660f..cfe7be9b16 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.3.9-next.2", + "version": "0.3.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,10 +49,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 0939b53154..8668e588fa 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-newrelic-dashboard +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 7673ba697b..d08ce75ef3 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.2-next.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,19 +22,19 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/dev-utils": "^1.0.6-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", "@testing-library/jest-dom": "^5.10.1", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5" diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 0c56ba254d..3748b744de 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-newrelic +## 0.3.27-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.27-next.2 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 0d858cdc93..978b0abddd 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.27-next.2", + "version": "0.3.27-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 883a613b88..568bba4890 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-org +## 0.5.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.5.9-next.2 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index a6701a3c1d..f62d938486 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.5.9-next.2", + "version": "0.5.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -28,10 +28,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,11 +47,11 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 42b61b3643..98485e3836 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-pagerduty +## 0.5.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.5.2-next.2 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index df5971497d..dda460bbb6 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.5.2-next.2", + "version": "0.5.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -52,10 +52,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index 5e01c50257..adf1520cf9 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-periskop-backend +## 0.1.7-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.7-next.2 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index 088fe43d9c..c49d71028e 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.1.7-next.2", + "version": "0.1.7-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,8 +23,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", "@types/express": "*", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -33,7 +33,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.6" diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 1e18571dc0..7b5cccc8d4 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-periskop +## 0.1.7-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 03a15b2b4a..b4494bc934 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.7-next.1", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -40,10 +40,10 @@ "react-dom": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index c8d4957c8a..615104ee9b 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-permission-backend +## 0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-permission-node@0.6.5-next.3 + ## 0.5.11-next.1 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 1b47c84061..42dd4fcd1c 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.11-next.1", + "version": "0.5.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,12 +22,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-node": "^0.6.5-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-node": "^0.6.5-next.3", "@types/express": "*", "dataloader": "^2.0.0", "express": "^4.17.1", @@ -39,7 +39,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index 592f6b4fdb..0a64a7faf8 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-permission-common +## 0.6.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + ## 0.6.4-next.1 ### Patch Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 6c3c9d2d29..5a6d98aba5 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.6.4-next.1", + "version": "0.6.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -41,14 +41,14 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "cross-fetch": "^3.1.5", "uuid": "^8.0.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "msw": "^0.47.0" } } diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 887061acbf..6ac474d76d 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-permission-node +## 0.6.5-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 0.6.5-next.2 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index ef8c932b68..6cb3f771d5 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.6.5-next.2", + "version": "0.6.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,19 +33,19 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index e4414a7daa..8cc4c02424 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-permission-react +## 0.4.5-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-permission-common@0.6.4-next.2 + ## 0.4.5-next.1 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 621379544c..82c5140f86 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.5-next.1", + "version": "0.4.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", - "@backstage/plugin-permission-common": "^0.6.4-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "cross-fetch": "^3.1.5", "react-use": "^17.2.4", "swr": "^1.1.2" @@ -44,8 +44,8 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3" }, diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index d76c3511f9..08e89d6910 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-proxy-backend +## 0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.2.30-next.1 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 1e7f7dc96e..1870c1ec7d 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.2.30-next.1", + "version": "0.2.30-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -46,7 +46,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index aaca8497da..8f821f6e8f 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-rollbar-backend +## 0.1.33-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.33-next.2 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index c0777e9950..eb3b74e69a 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.33-next.2", + "version": "0.1.33-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,8 +33,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", "@types/express": "^4.17.6", "camelcase-keys": "^7.0.1", "compression": "^1.7.4", @@ -49,8 +49,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 55926c9611..6d1464aa02 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-rollbar +## 0.4.9-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.4.9-next.2 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 769e002539..9cf5aa4964 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.9-next.2", + "version": "0.4.9-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index 495712b802..77c0282940 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.11-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + ## 0.2.11-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index a9c95cacb8..5c19a3d4cf 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.11-next.1", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-scaffolder-backend": "^1.6.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-scaffolder-backend": "^1.6.0-next.3", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", "fs-extra": "10.1.0", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index 15930b6b1d..ceb954110b 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.4-next.1 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + ## 0.4.4-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 3c47c435df..e60e643880 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.4-next.0", + "version": "0.4.4-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,17 +23,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.0", - "@backstage/plugin-scaffolder-backend": "^1.6.0-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-scaffolder-backend": "^1.6.0-next.3", "@backstage/types": "^1.0.0", "command-exists": "^1.2.9", "fs-extra": "^10.0.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 117dd2e7d0..1769ad172e 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.9-next.1 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-scaffolder-backend@1.6.0-next.3 + ## 0.2.9-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 0a8648134f..eac08016f8 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.9-next.0", + "version": "0.2.9-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,15 +22,15 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/plugin-scaffolder-backend": "^1.6.0-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-scaffolder-backend": "^1.6.0-next.3", "@backstage/types": "^1.0.0", "winston": "^3.2.1", "yeoman-environment": "^3.9.1" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.0", - "@backstage/cli": "^0.19.0-next.1" + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index b612234d50..bf0b46c509 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend +## 1.6.0-next.3 + +### Patch Changes + +- 50467bc15b: The number of task workers used to execute templates now default to 3, rather than 1. +- Updated dependencies + - @backstage/plugin-catalog-node@1.1.0-next.2 + - @backstage/backend-plugin-api@0.1.2-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-catalog-backend@1.4.0-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + - @backstage/plugin-auth-node@0.2.5-next.3 + ## 1.6.0-next.2 ### Minor Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 7f8d7e1f67..5b72ab2f07 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.6.0-next.2", + "version": "1.6.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,17 +34,17 @@ "build:assets": "node scripts/build-nunjucks.js" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-plugin-api": "^0.1.2-next.1", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-catalog-backend": "^1.4.0-next.2", - "@backstage/plugin-catalog-node": "^1.0.2-next.1", - "@backstage/plugin-scaffolder-common": "^1.2.0-next.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-plugin-api": "^0.1.2-next.2", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-catalog-backend": "^1.4.0-next.3", + "@backstage/plugin-catalog-node": "^1.1.0-next.2", + "@backstage/plugin-scaffolder-common": "^1.2.0-next.1", "@backstage/types": "^1.0.0", "@gitbeaker/core": "^35.6.0", "@gitbeaker/node": "^35.1.0", @@ -79,8 +79,8 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index 95a5c9061b..f7cdcfe3b0 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-scaffolder-common +## 1.2.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + ## 1.2.0-next.0 ### Minor Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 834e3e266a..40ef29a3ae 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.2.0-next.0", + "version": "1.2.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,10 +38,10 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", + "@backstage/catalog-model": "^1.1.1-next.0", "@backstage/types": "^1.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" } } diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index eccaecc152..d30be1c8fc 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder +## 1.6.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- 6522e459aa: Support displaying and ordering by counts in `EntityTagPicker` field. Add the `showCounts` option to enable this. Also support configuring `helperText`. +- f0510a20b5: Addition of a dismissible Error Banner in Scaffolder page +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-permission-react@0.4.5-next.2 + - @backstage/plugin-scaffolder-common@1.2.0-next.1 + ## 1.6.0-next.2 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 5416c0bb2c..d0387ef4fe 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.6.0-next.2", + "version": "1.6.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,18 +33,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/integration-react": "^1.1.4-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/integration-react": "^1.1.4-next.2", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-permission-react": "^0.4.5-next.1", - "@backstage/plugin-scaffolder-common": "^1.2.0-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-permission-react": "^0.4.5-next.2", + "@backstage/plugin-scaffolder-common": "^1.2.0-next.1", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", "@codemirror/language": "^6.0.0", @@ -79,11 +79,11 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/plugin-catalog": "^1.5.1-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/plugin-catalog": "^1.5.1-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 83f4cdab3e..01b3be70b1 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + ## 1.0.2-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 7b66d0c179..6ba1fe73d5 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.0.2-next.1", + "version": "1.0.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,8 +23,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/plugin-search-backend-node": "^1.0.2-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-search-backend-node": "^1.0.2-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@elastic/elasticsearch": "^7.13.0", "@opensearch-project/opensearch": "^2.0.0", @@ -36,8 +36,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/cli": "^0.19.0-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/cli": "^0.19.0-next.3", "@elastic/elasticsearch-mock": "^1.0.0", "@short.io/opensearch-mock": "^0.3.1" }, diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 93d0abe0be..2610be5997 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search-backend-module-pg +## 0.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + ## 0.4.0-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index f98e440972..cc04e46be1 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.4.0-next.1", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,17 +23,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/plugin-search-backend-node": "^1.0.2-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/plugin-search-backend-node": "^1.0.2-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "knex": "^2.0.0", "lodash": "^4.17.21", "uuid": "^8.3.2" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.1", - "@backstage/cli": "^0.19.0-next.1" + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index d5895611ab..dc16b57c18 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-search-backend-node +## 1.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 1.0.2-next.1 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 6899afb192..096deeab9e 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.0.2-next.1", + "version": "1.0.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,11 +23,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-permission-common": "^0.6.4-next.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@types/lunr": "^2.3.3", "lodash": "^4.17.21", @@ -38,8 +38,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/cli": "^0.19.0-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/ndjson": "^2.0.1" }, "files": [ diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index 6179dbff4f..0707bdd5d6 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search-backend +## 1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-auth-node@0.2.5-next.3 + - @backstage/plugin-permission-node@0.6.5-next.3 + - @backstage/plugin-search-backend-node@1.0.2-next.2 + ## 1.0.2-next.0 ### Patch Changes diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index c6a104b14e..56070040fd 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.0.2-next.0", + "version": "1.0.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,13 +23,13 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.1", - "@backstage/plugin-permission-common": "^0.6.4-next.0", - "@backstage/plugin-permission-node": "^0.6.5-next.1", - "@backstage/plugin-search-backend-node": "^1.0.2-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-node": "^0.6.5-next.3", + "@backstage/plugin-search-backend-node": "^1.0.2-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", @@ -43,7 +43,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 6358e0495f..b02bccd5ed 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-search +## 1.0.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 1.0.2-next.2 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 89401a8189..ad9d95e81f 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "1.0.2-next.2", + "version": "1.0.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/plugin-search-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.16", @@ -56,10 +56,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index ea399442f6..049627446c 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sentry +## 0.4.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.4.2-next.2 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index d23bd17cdb..b48f5b7489 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.4.2-next.2", + "version": "0.4.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-table/core": "^3.1.0", "@material-ui/core": "^4.12.2", @@ -51,10 +51,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index eed53a0314..8bf4e62b3a 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-shortcuts +## 0.3.1-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.1-next.2 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 80e0c75488..cf2038ffe3 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.3.1-next.2", + "version": "0.3.1-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,8 +23,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", @@ -41,10 +41,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index ddb7eb49b4..dae521af5f 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-sonarqube-backend +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.1-next.1 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 928c21f939..2ecc0e5d10 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.1.1-next.1", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,9 +22,9 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/express": "*", "express": "^4.18.1", "express-promise-router": "^4.1.0", @@ -33,8 +33,8 @@ "yn": "^5.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@types/supertest": "^2.0.12", "msw": "^0.47.0", "supertest": "^6.2.4" diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index a0c70158ce..9a33a45ebb 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-sonarqube +## 0.4.1-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.4.1-next.1 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index d4a36da284..422fcebcdf 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.4.1-next.1", + "version": "0.4.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,10 +34,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 7f9ee71ca2..a3c4536f17 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-splunk-on-call +## 0.3.33-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.3.33-next.2 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index f9e464819f..2ea4cbd62d 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.3.33-next.2", + "version": "0.3.33-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,10 +33,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -50,10 +50,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 0d47f9362e..f844a3de68 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-stack-overflow-backend +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/cli@0.19.0-next.3 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 2c4c18d9e8..9f12767ef1 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.1.5-next.1", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/config": "^1.0.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/config": "^1.0.2-next.0", "@backstage/plugin-search-common": "^1.0.1-next.0", "node-fetch": "^2.6.7", "qs": "^6.9.4", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index 815d381673..25c55415b3 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-stack-overflow +## 0.1.5-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/plugin-home@0.4.25-next.3 + ## 0.1.5-next.2 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index 156f7b1a26..e3b514fca1 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.5-next.2", + "version": "0.1.5-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/plugin-home": "^0.4.25-next.2", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/plugin-home": "^0.4.25-next.3", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", @@ -41,10 +41,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", "@types/node": "^16.11.26", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index 6951f1d4ef..27782333f2 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + ## 0.1.20-next.0 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index e2a46b05bd..7716a426ab 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.20-next.0", + "version": "0.1.20-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/plugin-tech-insights-common": "^0.2.6", - "@backstage/plugin-tech-insights-node": "^0.3.4-next.0", + "@backstage/plugin-tech-insights-node": "^0.3.4-next.1", "ajv": "^8.10.0", "json-rules-engine": "^6.1.2", "lodash": "^4.17.21", @@ -45,7 +45,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index 61a334770c..3daf38e0ef 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-tech-insights-backend +## 0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + - @backstage/plugin-tech-insights-node@0.3.4-next.1 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index 556ad5163c..cd4db90942 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,14 +33,14 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/catalog-client": "^1.0.5-next.0", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/plugin-tech-insights-common": "^0.2.6", - "@backstage/plugin-tech-insights-node": "^0.3.4-next.0", + "@backstage/plugin-tech-insights-node": "^0.3.4-next.1", "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", "express": "^4.17.1", @@ -54,8 +54,8 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.1", - "@backstage/cli": "^0.19.0-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", "@types/semver": "^7.3.8", "@types/supertest": "^2.0.8", "supertest": "^6.1.3", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 53e8b06716..0411c2fe2a 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-tech-insights-node +## 0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.3.4-next.0 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index e74b9df57f..41d4bebc62 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.3.4-next.0", + "version": "0.3.4-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/config": "^1.0.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/config": "^1.0.2-next.0", "@backstage/plugin-tech-insights-common": "^0.2.6", "@backstage/types": "^1.0.0", "@types/luxon": "^3.0.0", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 5f2c9347a5..44b9d666d8 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-tech-insights +## 0.3.0-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.3.0-next.2 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 836181aea6..4e521c6436 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.0-next.2", + "version": "0.3.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,11 +27,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-tech-insights-common": "^0.2.6", "@backstage/theme": "^0.2.16", "@backstage/types": "^1.0.0", @@ -46,10 +46,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index ef29d8e037..af98588824 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-tech-radar +## 0.5.16-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.5.16-next.2 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index f2d4fd5ee2..e2cdbae22b 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.5.16-next.2", + "version": "0.5.16-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -47,10 +47,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 288c24b4b9..ceb99b546b 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.4-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-app-api@1.1.0-next.3 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/test-utils@1.2.0-next.3 + - @backstage/plugin-catalog@1.5.1-next.3 + - @backstage/plugin-techdocs@1.3.2-next.3 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + ## 1.0.4-next.2 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 54548fb080..574503a9d8 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.4-next.2", + "version": "1.0.4-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,15 +32,15 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-catalog": "^1.5.1-next.2", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog": "^1.5.1-next.3", "@backstage/plugin-search-react": "^1.1.0-next.2", - "@backstage/plugin-techdocs": "^1.3.2-next.2", - "@backstage/plugin-techdocs-react": "^1.0.4-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/plugin-techdocs": "^1.3.2-next.3", + "@backstage/plugin-techdocs-react": "^1.0.4-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -56,8 +56,8 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 6b4d76b393..8e695b9426 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-techdocs-backend +## 1.3.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/plugin-permission-common@0.6.4-next.2 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/plugin-techdocs-node@1.4.0-next.2 + ## 1.3.0-next.1 ### Minor Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 9bed0743bd..6915d9b0b5 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.3.0-next.1", + "version": "1.3.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,16 +33,16 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/plugin-permission-common": "^0.6.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", - "@backstage/plugin-techdocs-node": "^1.4.0-next.1", + "@backstage/plugin-techdocs-node": "^1.4.0-next.2", "@types/express": "^4.17.6", "dockerode": "^3.3.1", "express": "^4.17.1", @@ -55,9 +55,9 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/cli": "^0.19.0-next.2", - "@backstage/plugin-search-backend-node": "1.0.2-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/plugin-search-backend-node": "1.0.2-next.2", "@types/dockerode": "^3.3.0", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index b683b09e89..ea008bb121 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.0.4-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + ## 1.0.4-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 35db982035..250394603c 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.0.4-next.1", + "version": "1.0.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-techdocs-react": "^1.0.4-next.1", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-techdocs-react": "^1.0.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", @@ -50,11 +50,11 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/plugin-techdocs-addons-test-utils": "^1.0.4-next.2", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/plugin-techdocs-addons-test-utils": "^1.0.4-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index f17a69ce4d..1dabca3005 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-node +## 1.4.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + ## 1.4.0-next.1 ### Minor Changes diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index f6d9042359..8bd6971528 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.4.0-next.1", + "version": "1.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -41,11 +41,11 @@ "dependencies": { "@azure/identity": "^2.0.1", "@azure/storage-blob": "^12.5.0", - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@google-cloud/storage": "^6.0.0", "@trendyol-js/openstack-swift-sdk": "^0.0.5", @@ -63,7 +63,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/fs-extra": "^9.0.5", "@types/js-yaml": "^4.0.0", "@types/mime-types": "^2.1.0", diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 07599edc75..b7223d3ba4 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-techdocs-react +## 1.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 1.0.4-next.1 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index f86ff600d8..d54de784aa 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.0.4-next.1", + "version": "1.0.4-next.2", "publishConfig": { "access": "public", "alphaTypes": "dist/index.alpha.d.ts", @@ -34,10 +34,10 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.1", - "@backstage/core-plugin-api": "^1.0.6-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/version-bridge": "^1.0.1", "@material-ui/core": "^4.12.2", "@material-ui/lab": "4.0.0-alpha.57", @@ -53,8 +53,8 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.1", - "@backstage/test-utils": "^1.2.0-next.1", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/test-utils": "^1.2.0-next.3", "@backstage/theme": "^0.2.16", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index b40aed750d..a89b1361ca 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-techdocs +## 1.3.2-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/integration-react@1.1.4-next.2 + - @backstage/plugin-techdocs-react@1.0.4-next.2 + ## 1.3.2-next.2 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 4ea6307408..e484b6ba07 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.3.2-next.2", + "version": "1.3.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,17 +33,17 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", - "@backstage/integration-react": "^1.1.4-next.1", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", + "@backstage/integration-react": "^1.1.4-next.2", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/plugin-search-common": "^1.0.1-next.0", "@backstage/plugin-search-react": "^1.1.0-next.2", - "@backstage/plugin-techdocs-react": "^1.0.4-next.1", + "@backstage/plugin-techdocs-react": "^1.0.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -65,10 +65,10 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index aca3dfb965..b77960123a 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo-backend +## 0.1.33-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.1.0-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/integration@1.3.1-next.2 + - @backstage/backend-common@0.15.1-next.3 + ## 0.1.33-next.1 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 1ecce23282..55bf606f4e 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.1.33-next.1", + "version": "0.1.33-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,12 +29,12 @@ "start": "backstage-cli package start" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/catalog-client": "^1.0.5-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/integration": "^1.3.1-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-client": "^1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/integration": "^1.3.1-next.2", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -43,7 +43,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 88d4812a28..da47468aa2 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-todo +## 0.2.11-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.11-next.2 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 880209654b..9ee1e06b98 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.11-next.2", + "version": "0.2.11-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,11 +29,11 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -45,10 +45,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index e720e3255d..e249499aa4 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-user-settings +## 0.4.8-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + ## 0.4.8-next.2 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 0f6ab5161b..f99c0d206e 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.4.8-next.2", + "version": "0.4.8-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,8 +32,8 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -46,10 +46,10 @@ "react-router": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 7d839d2f31..8ef29cf44a 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-vault-backend +## 0.2.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.0.2-next.0 + - @backstage/errors@1.1.1-next.0 + - @backstage/backend-test-utils@0.1.28-next.3 + - @backstage/backend-common@0.15.1-next.3 + - @backstage/backend-tasks@0.3.5-next.1 + ## 0.2.2-next.2 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index b6b59892e0..b90118bb66 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.2.2-next.2", + "version": "0.2.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-tasks": "^0.3.5-next.0", - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-tasks": "^0.3.5-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", "@types/express": "*", "compression": "^1.7.4", "cors": "^2.8.5", @@ -50,7 +50,7 @@ "yn": "^5.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/compression": "^1.7.2", "@types/supertest": "^2.0.8", "msw": "^0.47.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index e551781a71..852be0d87e 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-vault +## 0.1.3-next.2 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.1.4-next.2 + - @backstage/catalog-model@1.1.1-next.0 + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.1.3-next.1 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 00d4d4bf47..762a5328ea 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.3-next.1", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -48,10 +48,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index 8d64162dbe..b998a9955e 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-xcmetrics +## 0.2.29-next.3 + +### Patch Changes + +- 7d47def9c4: Removed dependency on `@types/jest`. +- Updated dependencies + - @backstage/core-components@0.11.1-next.3 + - @backstage/core-plugin-api@1.0.6-next.3 + - @backstage/errors@1.1.1-next.0 + ## 0.2.29-next.2 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 94cd0e8066..0b4099b691 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.29-next.2", + "version": "0.2.29-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -23,9 +23,9 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,10 +39,10 @@ "react": "^16.13.1 || ^17.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/user-event": "^14.0.0", diff --git a/yarn.lock b/yarn.lock index c772e1a835..8c36d1da02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2814,16 +2814,16 @@ __metadata: languageName: node linkType: hard -"@backstage/app-defaults@^1.0.6-next.1, @backstage/app-defaults@workspace:packages/app-defaults": +"@backstage/app-defaults@^1.0.6-next.2, @backstage/app-defaults@workspace:packages/app-defaults": version: 0.0.0-use.local resolution: "@backstage/app-defaults@workspace:packages/app-defaults" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-app-api": ^1.1.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/plugin-permission-react": ^0.4.5-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -2839,33 +2839,33 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-app-api@^0.2.1-next.0, @backstage/backend-app-api@^0.2.1-next.1, @backstage/backend-app-api@workspace:packages/backend-app-api": +"@backstage/backend-app-api@^0.2.1-next.2, @backstage/backend-app-api@workspace:packages/backend-app-api": version: 0.0.0-use.local resolution: "@backstage/backend-app-api@workspace:packages/backend-app-api" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-permission-node": ^0.6.5-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-permission-node": ^0.6.5-next.3 express: ^4.17.1 express-promise-router: ^4.1.0 winston: ^3.2.1 languageName: unknown linkType: soft -"@backstage/backend-common@^0.15.1-next.0, @backstage/backend-common@^0.15.1-next.1, @backstage/backend-common@^0.15.1-next.2, @backstage/backend-common@workspace:packages/backend-common": +"@backstage/backend-common@^0.15.1-next.3, @backstage/backend-common@workspace:packages/backend-common": version: 0.0.0-use.local resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/cli-common": ^0.1.9 - "@backstage/config": ^1.0.1 - "@backstage/config-loader": ^1.1.4-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 + "@backstage/config": ^1.0.2-next.0 + "@backstage/config-loader": ^1.1.4-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/types": ^1.0.0 "@google-cloud/storage": ^6.0.0 "@keyv/redis": ^2.2.3 @@ -2945,21 +2945,21 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/backend-defaults@workspace:packages/backend-defaults" dependencies: - "@backstage/backend-app-api": ^0.2.1-next.0 - "@backstage/backend-plugin-api": ^0.1.2-next.0 - "@backstage/cli": ^0.19.0-next.1 + "@backstage/backend-app-api": ^0.2.1-next.2 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/cli": ^0.19.0-next.3 languageName: unknown linkType: soft -"@backstage/backend-plugin-api@^0.1.2-next.0, @backstage/backend-plugin-api@^0.1.2-next.1, @backstage/backend-plugin-api@workspace:packages/backend-plugin-api": +"@backstage/backend-plugin-api@^0.1.2-next.2, @backstage/backend-plugin-api@workspace:packages/backend-plugin-api": version: 0.0.0-use.local resolution: "@backstage/backend-plugin-api@workspace:packages/backend-plugin-api" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/plugin-permission-common": ^0.6.4-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-permission-common": ^0.6.4-next.2 "@types/express": ^4.17.6 express: ^4.17.1 winston: ^3.2.1 @@ -2967,15 +2967,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-tasks@^0.3.5-next.0, @backstage/backend-tasks@workspace:packages/backend-tasks": +"@backstage/backend-tasks@^0.3.5-next.1, @backstage/backend-tasks@workspace:packages/backend-tasks": version: 0.0.0-use.local resolution: "@backstage/backend-tasks@workspace:packages/backend-tasks" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/types": ^1.0.0 "@types/cron": ^2.0.0 "@types/luxon": ^3.0.0 @@ -2991,15 +2991,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-test-utils@^0.1.28-next.1, @backstage/backend-test-utils@^0.1.28-next.2, @backstage/backend-test-utils@workspace:packages/backend-test-utils": +"@backstage/backend-test-utils@^0.1.28-next.3, @backstage/backend-test-utils@workspace:packages/backend-test-utils": version: 0.0.0-use.local resolution: "@backstage/backend-test-utils@workspace:packages/backend-test-utils" dependencies: - "@backstage/backend-app-api": ^0.2.1-next.1 - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-app-api": ^0.2.1-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 better-sqlite3: ^7.5.0 knex: ^2.0.0 msw: ^0.47.0 @@ -3010,13 +3010,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@^1.0.5-next.0, @backstage/catalog-client@^1.0.5-next.1, @backstage/catalog-client@workspace:packages/catalog-client": +"@backstage/catalog-client@^1.1.0-next.2, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/errors": ^1.1.0 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/errors": ^1.1.1-next.0 cross-fetch: ^3.1.5 msw: ^0.47.0 languageName: unknown @@ -3033,13 +3033,13 @@ __metadata: languageName: node linkType: hard -"@backstage/catalog-model@^1.0.0, @backstage/catalog-model@^1.0.1, @backstage/catalog-model@^1.0.3, @backstage/catalog-model@^1.1.0, @backstage/catalog-model@workspace:packages/catalog-model": +"@backstage/catalog-model@^1.1.1-next.0, @backstage/catalog-model@workspace:packages/catalog-model": version: 0.0.0-use.local resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/types": ^1.0.0 "@types/json-schema": ^7.0.5 "@types/lodash": ^4.14.151 @@ -3051,30 +3051,45 @@ __metadata: languageName: unknown linkType: soft -"@backstage/cli-common@^0.1.9, @backstage/cli-common@^0.1.9-next.0, @backstage/cli-common@workspace:packages/cli-common": +"@backstage/catalog-model@npm:^1.0.0, @backstage/catalog-model@npm:^1.1.0": + version: 1.1.0 + resolution: "@backstage/catalog-model@npm:1.1.0" + dependencies: + "@backstage/config": ^1.0.1 + "@backstage/errors": ^1.1.0 + "@backstage/types": ^1.0.0 + ajv: ^8.10.0 + json-schema: ^0.4.0 + lodash: ^4.17.21 + uuid: ^8.0.0 + checksum: 81db2da7f960e6207f2eeab3944d5bc54d739b6172575cf4cb9096a2058835af75534fd5232c450efddc8d656952ebbf130501ac0bba43690a3d742c3e11143d + languageName: node + linkType: hard + +"@backstage/cli-common@^0.1.10-next.0, @backstage/cli-common@workspace:packages/cli-common": version: 0.0.0-use.local resolution: "@backstage/cli-common@workspace:packages/cli-common" dependencies: - "@backstage/cli": ^0.19.0-next.1 + "@backstage/cli": ^0.19.0-next.3 "@types/node": ^16.0.0 languageName: unknown linkType: soft -"@backstage/cli@^0.19.0-next.1, @backstage/cli@^0.19.0-next.2, @backstage/cli@workspace:*, @backstage/cli@workspace:packages/cli": +"@backstage/cli@^0.19.0-next.1, @backstage/cli@^0.19.0-next.2, @backstage/cli@^0.19.0-next.3, @backstage/cli@workspace:*, @backstage/cli@workspace:packages/cli": version: 0.0.0-use.local resolution: "@backstage/cli@workspace:packages/cli" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli-common": ^0.1.9 - "@backstage/config": ^1.0.1 - "@backstage/config-loader": ^1.1.4-next.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/release-manifests": ^0.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli-common": ^0.1.10-next.0 + "@backstage/config": ^1.0.2-next.0 + "@backstage/config-loader": ^1.1.4-next.2 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/release-manifests": ^0.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@manypkg/get-packages": ^1.1.3 @@ -3204,8 +3219,8 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/codemods@workspace:packages/codemods" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/cli-common": ^0.1.9 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 "@types/jscodeshift": ^0.11.0 "@types/node": ^16.11.26 chalk: ^4.0.0 @@ -3218,14 +3233,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config-loader@^1.1.4-next.1, @backstage/config-loader@workspace:packages/config-loader": +"@backstage/config-loader@^1.1.4-next.2, @backstage/config-loader@workspace:packages/config-loader": version: 0.0.0-use.local resolution: "@backstage/config-loader@workspace:packages/config-loader" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/cli-common": ^0.1.9 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/types": ^1.0.0 "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 @@ -3247,26 +3262,36 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@^1.0.0, @backstage/config@^1.0.1, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.2-next.0, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@types/node": ^16.0.0 lodash: ^4.17.21 languageName: unknown linkType: soft -"@backstage/core-app-api@^1.1.0-next.1, @backstage/core-app-api@^1.1.0-next.2, @backstage/core-app-api@workspace:packages/core-app-api": +"@backstage/config@npm:^1.0.1": + version: 1.0.1 + resolution: "@backstage/config@npm:1.0.1" + dependencies: + "@backstage/types": ^1.0.0 + lodash: ^4.17.21 + checksum: 08ec95a9ddbfc8410c949314c464c63c0723a0681e21607463495454d7b06a9e7884110874efe7a9f7a8c9c864eb20a528a7a407dba7da84516d47d929e7ebc3 + languageName: node + linkType: hard + +"@backstage/core-app-api@^1.1.0-next.1, @backstage/core-app-api@^1.1.0-next.2, @backstage/core-app-api@^1.1.0-next.3, @backstage/core-app-api@workspace:packages/core-app-api": version: 0.0.0-use.local resolution: "@backstage/core-app-api@workspace:packages/core-app-api" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 "@testing-library/jest-dom": ^5.10.1 @@ -3293,16 +3318,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/core-components@^0.11.1-next.1, @backstage/core-components@^0.11.1-next.2, @backstage/core-components@workspace:packages/core-components": +"@backstage/core-components@^0.11.1-next.1, @backstage/core-components@^0.11.1-next.2, @backstage/core-components@^0.11.1-next.3, @backstage/core-components@workspace:packages/core-components": version: 0.0.0-use.local resolution: "@backstage/core-components@workspace:packages/core-components" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/version-bridge": ^1.0.1 "@material-table/core": ^3.1.0 @@ -3416,14 +3441,14 @@ __metadata: languageName: node linkType: hard -"@backstage/core-plugin-api@^1.0.6-next.1, @backstage/core-plugin-api@^1.0.6-next.2, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@^1.0.6-next.1, @backstage/core-plugin-api@^1.0.6-next.2, @backstage/core-plugin-api@^1.0.6-next.3, @backstage/core-plugin-api@workspace:packages/core-plugin-api": version: 0.0.0-use.local resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 "@testing-library/jest-dom": ^5.10.1 @@ -3467,8 +3492,8 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/create-app@workspace:packages/create-app" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/cli-common": ^0.1.9 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 "@types/fs-extra": ^9.0.1 "@types/inquirer": ^8.1.3 "@types/node": ^16.11.26 @@ -3487,19 +3512,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/dev-utils@^1.0.6-next.1, @backstage/dev-utils@workspace:packages/dev-utils": +"@backstage/dev-utils@^1.0.6-next.1, @backstage/dev-utils@^1.0.6-next.2, @backstage/dev-utils@workspace:packages/dev-utils": version: 0.0.0-use.local resolution: "@backstage/dev-utils@workspace:packages/dev-utils" dependencies: - "@backstage/app-defaults": ^1.0.6-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-app-api": ^1.1.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/integration-react": ^1.1.4-next.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/app-defaults": ^1.0.6-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3518,28 +3543,39 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@1.1.0, @backstage/errors@^1.0.0, @backstage/errors@^1.1.0, @backstage/errors@^1.1.0-next.0, @backstage/errors@workspace:packages/errors": +"@backstage/errors@1.1.1-next.0, @backstage/errors@^1.1.1-next.0, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: - "@backstage/cli": ^0.19.0-next.1 + "@backstage/cli": ^0.19.0-next.3 "@backstage/types": ^1.0.0 cross-fetch: ^3.1.5 serialize-error: ^8.0.1 languageName: unknown linkType: soft -"@backstage/integration-react@^1.1.4-next.0, @backstage/integration-react@^1.1.4-next.1, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/errors@npm:^1.1.0": + version: 1.1.0 + resolution: "@backstage/errors@npm:1.1.0" + dependencies: + "@backstage/types": ^1.0.0 + cross-fetch: ^3.1.5 + serialize-error: ^8.0.1 + checksum: b21d35803ce1adf7c7d7219e02636340780dc7f007bdaa966f62120f3607548a5e7a557b364abf54da29081f30efe3df72c5bfefebde335c305034961c6ae620 + languageName: node + linkType: hard + +"@backstage/integration-react@^1.1.4-next.2, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3575,15 +3611,15 @@ __metadata: languageName: node linkType: hard -"@backstage/integration@^1.3.1-next.0, @backstage/integration@^1.3.1-next.1, @backstage/integration@workspace:packages/integration": +"@backstage/integration@^1.3.1-next.1, @backstage/integration@^1.3.1-next.2, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/config-loader": ^1.1.4-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/config-loader": ^1.1.4-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@octokit/auth-app": ^4.0.0 "@octokit/rest": ^19.0.3 "@types/luxon": ^3.0.0 @@ -3615,14 +3651,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-adr-backend@workspace:plugins/adr-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-adr-common": ^0.2.1-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-adr-common": ^0.2.1-next.1 "@backstage/plugin-search-common": ^1.0.1-next.0 "@types/marked": ^4.0.0 "@types/supertest": ^2.0.8 @@ -3636,13 +3672,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-adr-common@^0.2.1-next.0, @backstage/plugin-adr-common@workspace:plugins/adr-common": +"@backstage/plugin-adr-common@^0.2.1-next.1, @backstage/plugin-adr-common@workspace:plugins/adr-common": version: 0.0.0-use.local resolution: "@backstage/plugin-adr-common@workspace:plugins/adr-common" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/integration": ^1.3.1-next.0 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 languageName: unknown linkType: soft @@ -3651,18 +3687,18 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-adr@workspace:plugins/adr" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-adr-common": ^0.2.1-next.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-adr-common": ^0.2.1-next.1 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3689,9 +3725,9 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-airbrake-backend@workspace:plugins/airbrake-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@types/express": "*" "@types/http-proxy-middleware": ^0.19.3 "@types/supertest": ^2.0.8 @@ -3705,18 +3741,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-airbrake@^0.3.9-next.2, @backstage/plugin-airbrake@workspace:plugins/airbrake": +"@backstage/plugin-airbrake@^0.3.9-next.3, @backstage/plugin-airbrake@workspace:plugins/airbrake": version: 0.0.0-use.local resolution: "@backstage/plugin-airbrake@workspace:plugins/airbrake" dependencies: - "@backstage/app-defaults": ^1.0.6-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/app-defaults": ^1.0.6-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3740,14 +3776,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-allure@workspace:plugins/allure" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3769,13 +3805,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-analytics-module-ga@workspace:plugins/analytics-module-ga" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3793,16 +3829,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-apache-airflow@^0.2.2-next.2, @backstage/plugin-apache-airflow@workspace:plugins/apache-airflow": +"@backstage/plugin-apache-airflow@^0.2.2-next.3, @backstage/plugin-apache-airflow@workspace:plugins/apache-airflow": version: 0.0.0-use.local resolution: "@backstage/plugin-apache-airflow@workspace:plugins/apache-airflow" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 @@ -3832,20 +3868,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-api-docs@^0.8.9-next.2, @backstage/plugin-api-docs@workspace:plugins/api-docs": +"@backstage/plugin-api-docs@^0.8.9-next.3, @backstage/plugin-api-docs@workspace:plugins/api-docs": version: 0.0.0-use.local resolution: "@backstage/plugin-api-docs@workspace:plugins/api-docs" dependencies: "@asyncapi/react-component": 1.0.0-next.40 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog": ^1.5.1-next.2 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -3876,12 +3912,12 @@ __metadata: resolution: "@backstage/plugin-apollo-explorer@workspace:plugins/apollo-explorer" dependencies: "@apollo/explorer": ^1.1.1 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 @@ -3899,15 +3935,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-app-backend@^0.3.36-next.2, @backstage/plugin-app-backend@workspace:plugins/app-backend": +"@backstage/plugin-app-backend@^0.3.36-next.3, @backstage/plugin-app-backend@workspace:plugins/app-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-app-backend@workspace:plugins/app-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/config-loader": ^1.1.4-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/config-loader": ^1.1.4-next.2 "@backstage/types": ^1.0.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 @@ -3927,18 +3963,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-backend@^0.16.0-next.2, @backstage/plugin-auth-backend@workspace:plugins/auth-backend": +"@backstage/plugin-auth-backend@^0.16.0-next.3, @backstage/plugin-auth-backend@workspace:plugins/auth-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend@workspace:plugins/auth-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 "@backstage/types": ^1.0.0 "@davidzemon/passport-okta-oauth": ^0.0.5 "@google-cloud/firestore": ^6.0.0 @@ -3991,15 +4027,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-node@^0.2.5-next.1, @backstage/plugin-auth-node@^0.2.5-next.2, @backstage/plugin-auth-node@workspace:plugins/auth-node": +"@backstage/plugin-auth-node@^0.2.5-next.3, @backstage/plugin-auth-node@workspace:plugins/auth-node": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-node@workspace:plugins/auth-node" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@types/express": "*" express: ^4.17.1 jose: ^4.6.0 @@ -4011,13 +4047,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-azure-devops-backend@^0.3.15-next.1, @backstage/plugin-azure-devops-backend@workspace:plugins/azure-devops-backend": +"@backstage/plugin-azure-devops-backend@^0.3.15-next.2, @backstage/plugin-azure-devops-backend@workspace:plugins/azure-devops-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-azure-devops-backend@workspace:plugins/azure-devops-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@backstage/plugin-azure-devops-common": ^0.3.0-next.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 @@ -4041,20 +4077,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-azure-devops@^0.2.0-next.2, @backstage/plugin-azure-devops@workspace:plugins/azure-devops": +"@backstage/plugin-azure-devops@^0.2.0-next.3, @backstage/plugin-azure-devops@workspace:plugins/azure-devops": version: 0.0.0-use.local resolution: "@backstage/plugin-azure-devops@workspace:plugins/azure-devops" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 "@backstage/plugin-azure-devops-common": ^0.3.0-next.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4074,16 +4110,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-badges-backend@^0.1.30-next.0, @backstage/plugin-badges-backend@workspace:plugins/badges-backend": +"@backstage/plugin-badges-backend@^0.1.30-next.1, @backstage/plugin-badges-backend@workspace:plugins/badges-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-badges-backend@workspace:plugins/badges-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/catalog-client": ^1.0.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 badge-maker: ^3.3.0 @@ -4096,19 +4132,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-badges@^0.2.33-next.2, @backstage/plugin-badges@workspace:plugins/badges": +"@backstage/plugin-badges@^0.2.33-next.3, @backstage/plugin-badges@workspace:plugins/badges": version: 0.0.0-use.local resolution: "@backstage/plugin-badges@workspace:plugins/badges" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4130,10 +4166,10 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-bazaar-backend@workspace:plugins/bazaar-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@types/express": ^4.17.6 express: ^4.17.1 express-promise-router: ^4.1.0 @@ -4147,14 +4183,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-bazaar@workspace:plugins/bazaar" dependencies: - "@backstage/catalog-client": ^1.0.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog": ^1.5.1-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@date-io/luxon": 1.x "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4188,14 +4224,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-bitrise@workspace:plugins/bitrise" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4221,14 +4257,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-aws@workspace:plugins/catalog-backend-module-aws" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.0 - "@backstage/plugin-catalog-backend": ^1.4.0-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@backstage/types": ^1.0.0 "@types/lodash": ^4.14.151 aws-sdk: ^2.840.0 @@ -4245,15 +4281,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-azure@workspace:plugins/catalog-backend-module-azure" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@backstage/types": ^1.0.0 "@types/lodash": ^4.14.151 lodash: ^4.17.21 @@ -4268,14 +4304,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-bitbucket-cloud@workspace:plugins/catalog-backend-module-bitbucket-cloud" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-bitbucket-cloud-common": ^0.1.3-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 msw: ^0.47.0 uuid: ^8.0.0 winston: ^3.2.1 @@ -4286,15 +4322,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-bitbucket-server@workspace:plugins/catalog-backend-module-bitbucket-server" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.0.1 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.0 - "@backstage/errors": ^1.0.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@types/node-fetch": ^2.5.12 msw: ^0.47.0 node-fetch: ^2.6.7 @@ -4307,15 +4343,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-bitbucket@workspace:plugins/catalog-backend-module-bitbucket" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-bitbucket-cloud-common": ^0.1.3-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@backstage/types": ^1.0.0 "@types/lodash": ^4.14.151 lodash: ^4.17.21 @@ -4329,15 +4365,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-gerrit@workspace:plugins/catalog-backend-module-gerrit" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@types/fs-extra": ^9.0.1 fs-extra: 10.1.0 msw: ^0.47.0 @@ -4351,17 +4387,17 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-github@workspace:plugins/catalog-backend-module-github" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 - "@backstage/plugin-catalog-node": ^1.0.2-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 + "@backstage/plugin-catalog-node": ^1.1.0-next.2 "@backstage/types": ^1.0.0 "@octokit/graphql": ^5.0.0 "@types/lodash": ^4.14.151 @@ -4377,15 +4413,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-gitlab@workspace:plugins/catalog-backend-module-gitlab" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@backstage/types": ^1.0.0 "@types/lodash": ^4.14.151 "@types/uuid": ^8.0.0 @@ -4401,12 +4437,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-ldap@workspace:plugins/catalog-backend-module-ldap" dependencies: - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-backend": ^1.4.0-next.1 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@backstage/types": ^1.0.0 "@types/ldapjs": ^2.2.0 "@types/lodash": ^4.14.151 @@ -4422,13 +4458,13 @@ __metadata: resolution: "@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph" dependencies: "@azure/identity": ^2.1.0 - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 "@microsoft/microsoft-graph-types": ^2.6.0 "@types/lodash": ^4.14.151 "@types/node-fetch": ^2.5.12 @@ -4447,14 +4483,14 @@ __metadata: resolution: "@backstage/plugin-catalog-backend-module-openapi@workspace:plugins/catalog-backend-module-openapi" dependencies: "@apidevtools/swagger-parser": ^10.1.0 - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/integration": ^1.3.1-next.0 - "@backstage/plugin-catalog-backend": ^1.4.0-next.1 - "@backstage/plugin-catalog-node": ^1.0.2-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 + "@backstage/plugin-catalog-node": ^1.1.0-next.2 "@backstage/types": ^1.0.0 openapi-types: ^12.0.0 winston: ^3.2.1 @@ -4462,25 +4498,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-backend@^1.4.0-next.1, @backstage/plugin-catalog-backend@^1.4.0-next.2, @backstage/plugin-catalog-backend@workspace:plugins/catalog-backend": +"@backstage/plugin-catalog-backend@^1.4.0-next.1, @backstage/plugin-catalog-backend@^1.4.0-next.3, @backstage/plugin-catalog-backend@workspace:plugins/catalog-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend@workspace:plugins/catalog-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-catalog-node": ^1.0.2-next.1 - "@backstage/plugin-permission-common": ^0.6.4-next.1 - "@backstage/plugin-permission-node": ^0.6.5-next.2 - "@backstage/plugin-scaffolder-common": ^1.2.0-next.0 - "@backstage/plugin-search-backend-node": 1.0.2-next.1 + "@backstage/plugin-catalog-node": ^1.1.0-next.2 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-node": ^0.6.5-next.3 + "@backstage/plugin-scaffolder-common": ^1.2.0-next.1 + "@backstage/plugin-search-backend-node": 1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/types": ^1.0.0 "@types/core-js": ^2.5.4 @@ -4535,20 +4571,20 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-catalog-graph@^0.2.21-next.1, @backstage/plugin-catalog-graph@workspace:plugins/catalog-graph": +"@backstage/plugin-catalog-graph@^0.2.21-next.2, @backstage/plugin-catalog-graph@workspace:plugins/catalog-graph": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-graph@workspace:plugins/catalog-graph" dependencies: - "@backstage/catalog-client": ^1.0.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-app-api": ^1.1.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog": ^1.5.1-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -4570,14 +4606,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-graphql@^0.3.13-next.2, @backstage/plugin-catalog-graphql@workspace:plugins/catalog-graphql": +"@backstage/plugin-catalog-graphql@^0.3.13-next.3, @backstage/plugin-catalog-graphql@workspace:plugins/catalog-graphql": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-graphql@workspace:plugins/catalog-graphql" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@graphql-codegen/cli": ^2.3.1 "@graphql-codegen/graphql-modules-preset": ^2.3.2 @@ -4595,23 +4631,23 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-import@^0.8.12-next.2, @backstage/plugin-catalog-import@workspace:plugins/catalog-import": +"@backstage/plugin-catalog-import@^0.8.12-next.3, @backstage/plugin-catalog-import@workspace:plugins/catalog-import": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-import@workspace:plugins/catalog-import" dependencies: - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 @@ -4635,38 +4671,38 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-node@^1.0.2-next.0, @backstage/plugin-catalog-node@^1.0.2-next.1, @backstage/plugin-catalog-node@workspace:plugins/catalog-node": +"@backstage/plugin-catalog-node@^1.1.0-next.2, @backstage/plugin-catalog-node@workspace:plugins/catalog-node": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-node@workspace:plugins/catalog-node" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/errors": 1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/errors": 1.1.1-next.0 "@backstage/types": ^1.0.0 languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@^1.1.4-next.0, @backstage/plugin-catalog-react@^1.1.4-next.1, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@^1.1.4-next.0, @backstage/plugin-catalog-react@^1.1.4-next.2, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: - "@backstage/catalog-client": ^1.0.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-app-api": ^1.1.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.0 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-permission-common": ^0.6.4-next.0 - "@backstage/plugin-permission-react": ^0.4.5-next.1 - "@backstage/plugin-scaffolder-common": ^1.2.0-next.0 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/plugin-scaffolder-common": ^1.2.0-next.1 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 @@ -4729,25 +4765,25 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-catalog@^1.5.1-next.0, @backstage/plugin-catalog@^1.5.1-next.1, @backstage/plugin-catalog@^1.5.1-next.2, @backstage/plugin-catalog@workspace:plugins/catalog": +"@backstage/plugin-catalog@^1.5.1-next.0, @backstage/plugin-catalog@^1.5.1-next.3, @backstage/plugin-catalog@workspace:plugins/catalog": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog@workspace:plugins/catalog" dependencies: - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration-react": ^1.1.4-next.1 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration-react": ^1.1.4-next.2 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-permission-react": ^0.4.5-next.1 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-permission-react": ^0.4.5-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -4773,10 +4809,10 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-cicd-statistics-module-gitlab@workspace:plugins/cicd-statistics-module-gitlab" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/plugin-cicd-statistics": ^0.1.11-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/plugin-cicd-statistics": ^0.1.11-next.2 "@gitbeaker/browser": ^35.6.0 "@gitbeaker/core": ^35.6.0 luxon: ^3.0.0 @@ -4784,14 +4820,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-cicd-statistics@^0.1.11-next.1, @backstage/plugin-cicd-statistics@workspace:plugins/cicd-statistics": +"@backstage/plugin-cicd-statistics@^0.1.11-next.2, @backstage/plugin-cicd-statistics@workspace:plugins/cicd-statistics": version: 0.0.0-use.local resolution: "@backstage/plugin-cicd-statistics@workspace:plugins/cicd-statistics" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@date-io/luxon": ^1.3.13 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.11.2 @@ -4810,18 +4846,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-circleci@^0.3.9-next.2, @backstage/plugin-circleci@workspace:plugins/circleci": +"@backstage/plugin-circleci@^0.3.9-next.3, @backstage/plugin-circleci@workspace:plugins/circleci": version: 0.0.0-use.local resolution: "@backstage/plugin-circleci@workspace:plugins/circleci" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4845,18 +4881,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-cloudbuild@^0.3.9-next.2, @backstage/plugin-cloudbuild@workspace:plugins/cloudbuild": +"@backstage/plugin-cloudbuild@^0.3.9-next.3, @backstage/plugin-cloudbuild@workspace:plugins/cloudbuild": version: 0.0.0-use.local resolution: "@backstage/plugin-cloudbuild@workspace:plugins/cloudbuild" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4881,13 +4917,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-code-climate@workspace:plugins/code-climate" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4909,17 +4945,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-code-coverage-backend@^0.2.2-next.1, @backstage/plugin-code-coverage-backend@workspace:plugins/code-coverage-backend": +"@backstage/plugin-code-coverage-backend@^0.2.2-next.2, @backstage/plugin-code-coverage-backend@workspace:plugins/code-coverage-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-code-coverage-backend@workspace:plugins/code-coverage-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@types/express": ^4.17.6 "@types/express-xml-bodyparser": ^0.3.2 "@types/supertest": ^2.0.8 @@ -4936,20 +4972,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-code-coverage@^0.2.2-next.2, @backstage/plugin-code-coverage@workspace:plugins/code-coverage": +"@backstage/plugin-code-coverage@^0.2.2-next.3, @backstage/plugin-code-coverage@workspace:plugins/code-coverage": version: 0.0.0-use.local resolution: "@backstage/plugin-code-coverage@workspace:plugins/code-coverage" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -4978,14 +5014,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-codescene@workspace:plugins/codescene" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.9.10 "@material-ui/icons": ^4.9.1 @@ -5008,14 +5044,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-config-schema@workspace:plugins/config-schema" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -5043,19 +5079,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-cost-insights@^0.11.31-next.2, @backstage/plugin-cost-insights@workspace:plugins/cost-insights": +"@backstage/plugin-cost-insights@^0.11.31-next.3, @backstage/plugin-cost-insights@workspace:plugins/cost-insights": version: 0.0.0-use.local resolution: "@backstage/plugin-cost-insights@workspace:plugins/cost-insights" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 "@backstage/plugin-cost-insights-common": ^0.1.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5088,17 +5124,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-dynatrace@^0.2.0-next.2, @backstage/plugin-dynatrace@workspace:plugins/dynatrace": +"@backstage/plugin-dynatrace@^0.2.0-next.3, @backstage/plugin-dynatrace@workspace:plugins/dynatrace": version: 0.0.0-use.local resolution: "@backstage/plugin-dynatrace@workspace:plugins/dynatrace" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 @@ -5116,14 +5152,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-explore-react@^0.0.21-next.2, @backstage/plugin-explore-react@workspace:plugins/explore-react": +"@backstage/plugin-explore-react@^0.0.21-next.3, @backstage/plugin-explore-react@workspace:plugins/explore-react": version: 0.0.0-use.local resolution: "@backstage/plugin-explore-react@workspace:plugins/explore-react" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/user-event": ^14.0.0 @@ -5133,19 +5169,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-explore@^0.3.40-next.2, @backstage/plugin-explore@workspace:plugins/explore": +"@backstage/plugin-explore@^0.3.40-next.3, @backstage/plugin-explore@workspace:plugins/explore": version: 0.0.0-use.local resolution: "@backstage/plugin-explore@workspace:plugins/explore" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-explore-react": ^0.0.21-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-explore-react": ^0.0.21-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5170,13 +5206,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-firehydrant@workspace:plugins/firehydrant" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5198,15 +5234,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-fossa@workspace:plugins/fossa" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5225,17 +5261,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-gcalendar@^0.3.5-next.2, @backstage/plugin-gcalendar@workspace:plugins/gcalendar": +"@backstage/plugin-gcalendar@^0.3.5-next.3, @backstage/plugin-gcalendar@workspace:plugins/gcalendar": version: 0.0.0-use.local resolution: "@backstage/plugin-gcalendar@workspace:plugins/gcalendar" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5261,16 +5297,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-gcp-projects@^0.3.28-next.2, @backstage/plugin-gcp-projects@workspace:plugins/gcp-projects": +"@backstage/plugin-gcp-projects@^0.3.28-next.3, @backstage/plugin-gcp-projects@workspace:plugins/gcp-projects": version: 0.0.0-use.local resolution: "@backstage/plugin-gcp-projects@workspace:plugins/gcp-projects" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5292,13 +5328,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-git-release-manager@workspace:plugins/git-release-manager" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5323,19 +5359,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-github-actions@^0.5.9-next.2, @backstage/plugin-github-actions@workspace:plugins/github-actions": +"@backstage/plugin-github-actions@^0.5.9-next.3, @backstage/plugin-github-actions@workspace:plugins/github-actions": version: 0.0.0-use.local resolution: "@backstage/plugin-github-actions@workspace:plugins/github-actions" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5360,17 +5396,17 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-github-deployments@workspace:plugins/github-deployments" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5393,16 +5429,16 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-github-issues@workspace:plugins/github-issues" dependencies: - "@backstage/catalog-model": ^1.0.3 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.15 "@material-ui/core": ^4.12.4 "@material-ui/icons": ^4.9.1 @@ -5427,14 +5463,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-github-pull-requests-board@workspace:plugins/github-pull-requests-board" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5459,12 +5495,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-gitops-profiles@workspace:plugins/gitops-profiles" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5482,19 +5518,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-gocd@^0.1.15-next.1, @backstage/plugin-gocd@workspace:plugins/gocd": +"@backstage/plugin-gocd@^0.1.15-next.2, @backstage/plugin-gocd@workspace:plugins/gocd": version: 0.0.0-use.local resolution: "@backstage/plugin-gocd@workspace:plugins/gocd" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5516,16 +5552,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-graphiql@^0.2.41-next.2, @backstage/plugin-graphiql@workspace:plugins/graphiql": +"@backstage/plugin-graphiql@^0.2.41-next.3, @backstage/plugin-graphiql@workspace:plugins/graphiql": version: 0.0.0-use.local resolution: "@backstage/plugin-graphiql@workspace:plugins/graphiql" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5547,14 +5583,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-graphql-backend@^0.1.26-next.2, @backstage/plugin-graphql-backend@workspace:plugins/graphql-backend": +"@backstage/plugin-graphql-backend@^0.1.26-next.3, @backstage/plugin-graphql-backend@workspace:plugins/graphql-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-graphql-backend@workspace:plugins/graphql-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/plugin-catalog-graphql": ^0.3.13-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-catalog-graphql": ^0.3.13-next.3 "@graphql-tools/schema": ^9.0.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 @@ -5573,20 +5609,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home@^0.4.25-next.2, @backstage/plugin-home@workspace:plugins/home": +"@backstage/plugin-home@^0.4.25-next.3, @backstage/plugin-home@workspace:plugins/home": version: 0.0.0-use.local resolution: "@backstage/plugin-home@workspace:plugins/home" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-stack-overflow": ^0.1.5-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-stack-overflow": ^0.1.5-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5634,15 +5670,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-ilert@workspace:plugins/ilert" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@date-io/luxon": 1.x "@material-ui/core": ^4.12.2 @@ -5663,19 +5699,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-jenkins-backend@^0.1.26-next.2, @backstage/plugin-jenkins-backend@workspace:plugins/jenkins-backend": +"@backstage/plugin-jenkins-backend@^0.1.26-next.3, @backstage/plugin-jenkins-backend@workspace:plugins/jenkins-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-jenkins-backend@workspace:plugins/jenkins-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 "@backstage/plugin-jenkins-common": ^0.1.8-next.0 - "@backstage/plugin-permission-common": ^0.6.4-next.1 + "@backstage/plugin-permission-common": ^0.6.4-next.2 "@types/express": ^4.17.6 "@types/jenkins": ^0.23.1 "@types/supertest": ^2.0.8 @@ -5700,20 +5736,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-jenkins@^0.7.8-next.2, @backstage/plugin-jenkins@workspace:plugins/jenkins": +"@backstage/plugin-jenkins@^0.7.8-next.3, @backstage/plugin-jenkins@workspace:plugins/jenkins": version: 0.0.0-use.local resolution: "@backstage/plugin-jenkins@workspace:plugins/jenkins" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@backstage/plugin-jenkins-common": ^0.1.8-next.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5734,15 +5770,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-kafka-backend@^0.2.29-next.0, @backstage/plugin-kafka-backend@workspace:plugins/kafka-backend": +"@backstage/plugin-kafka-backend@^0.2.29-next.1, @backstage/plugin-kafka-backend@workspace:plugins/kafka-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-kafka-backend@workspace:plugins/kafka-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@types/express": ^4.17.6 "@types/jest-when": ^3.5.0 "@types/lodash": ^4.14.151 @@ -5756,19 +5792,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-kafka@^0.3.9-next.2, @backstage/plugin-kafka@workspace:plugins/kafka": +"@backstage/plugin-kafka@^0.3.9-next.3, @backstage/plugin-kafka@workspace:plugins/kafka": version: 0.0.0-use.local resolution: "@backstage/plugin-kafka@workspace:plugins/kafka" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5788,19 +5824,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-kubernetes-backend@^0.7.2-next.2, @backstage/plugin-kubernetes-backend@workspace:plugins/kubernetes-backend": +"@backstage/plugin-kubernetes-backend@^0.7.2-next.3, @backstage/plugin-kubernetes-backend@workspace:plugins/kubernetes-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-kubernetes-backend@workspace:plugins/kubernetes-backend" dependencies: "@azure/identity": ^2.0.4 - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.2 - "@backstage/plugin-kubernetes-common": ^0.4.2-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-kubernetes-common": ^0.4.2-next.1 "@google-cloud/container": ^4.0.0 "@kubernetes/client-node": ^0.17.0 "@types/aws4": ^1.5.1 @@ -5825,30 +5861,30 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-kubernetes-common@^0.4.2-next.0, @backstage/plugin-kubernetes-common@workspace:plugins/kubernetes-common": +"@backstage/plugin-kubernetes-common@^0.4.2-next.1, @backstage/plugin-kubernetes-common@workspace:plugins/kubernetes-common": version: 0.0.0-use.local resolution: "@backstage/plugin-kubernetes-common@workspace:plugins/kubernetes-common" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 "@kubernetes/client-node": ^0.17.0 languageName: unknown linkType: soft -"@backstage/plugin-kubernetes@^0.7.2-next.2, @backstage/plugin-kubernetes@workspace:plugins/kubernetes": +"@backstage/plugin-kubernetes@^0.7.2-next.3, @backstage/plugin-kubernetes@workspace:plugins/kubernetes": version: 0.0.0-use.local resolution: "@backstage/plugin-kubernetes@workspace:plugins/kubernetes" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-kubernetes-common": ^0.4.2-next.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-kubernetes-common": ^0.4.2-next.1 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@kubernetes/client-node": ^0.17.0 "@material-ui/core": ^4.12.2 @@ -5873,19 +5909,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-lighthouse@^0.3.9-next.2, @backstage/plugin-lighthouse@workspace:plugins/lighthouse": +"@backstage/plugin-lighthouse@^0.3.9-next.3, @backstage/plugin-lighthouse@workspace:plugins/lighthouse": version: 0.0.0-use.local resolution: "@backstage/plugin-lighthouse@workspace:plugins/lighthouse" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5905,17 +5941,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-newrelic-dashboard@^0.2.2-next.1, @backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard": +"@backstage/plugin-newrelic-dashboard@^0.2.2-next.2, @backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard": version: 0.0.0-use.local resolution: "@backstage/plugin-newrelic-dashboard@workspace:plugins/newrelic-dashboard" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 @@ -5928,16 +5964,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-newrelic@^0.3.27-next.2, @backstage/plugin-newrelic@workspace:plugins/newrelic": +"@backstage/plugin-newrelic@^0.3.27-next.3, @backstage/plugin-newrelic@workspace:plugins/newrelic": version: 0.0.0-use.local resolution: "@backstage/plugin-newrelic@workspace:plugins/newrelic" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5954,19 +5990,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-org@^0.5.9-next.2, @backstage/plugin-org@workspace:plugins/org": +"@backstage/plugin-org@^0.5.9-next.3, @backstage/plugin-org@workspace:plugins/org": version: 0.0.0-use.local resolution: "@backstage/plugin-org@workspace:plugins/org" dependencies: - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -5988,19 +6024,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-pagerduty@0.5.2-next.2, @backstage/plugin-pagerduty@workspace:plugins/pagerduty": +"@backstage/plugin-pagerduty@0.5.2-next.3, @backstage/plugin-pagerduty@workspace:plugins/pagerduty": version: 0.0.0-use.local resolution: "@backstage/plugin-pagerduty@workspace:plugins/pagerduty" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6025,9 +6061,9 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-periskop-backend@workspace:plugins/periskop-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@types/express": "*" "@types/supertest": ^2.0.8 express: ^4.17.1 @@ -6044,15 +6080,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-periskop@workspace:plugins/periskop" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6072,17 +6108,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-backend@^0.5.11-next.1, @backstage/plugin-permission-backend@workspace:plugins/permission-backend": +"@backstage/plugin-permission-backend@^0.5.11-next.2, @backstage/plugin-permission-backend@workspace:plugins/permission-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-backend@workspace:plugins/permission-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.2 - "@backstage/plugin-permission-common": ^0.6.4-next.1 - "@backstage/plugin-permission-node": ^0.6.5-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-node": ^0.6.5-next.3 "@types/express": "*" "@types/lodash": ^4.14.151 "@types/supertest": ^2.0.8 @@ -6099,13 +6135,13 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@^0.6.4-next.0, @backstage/plugin-permission-common@^0.6.4-next.1, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@backstage/plugin-permission-common@^0.6.4-next.0, @backstage/plugin-permission-common@^0.6.4-next.2, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 cross-fetch: ^3.1.5 msw: ^0.47.0 uuid: ^8.0.0 @@ -6126,17 +6162,17 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-permission-node@^0.6.5-next.1, @backstage/plugin-permission-node@^0.6.5-next.2, @backstage/plugin-permission-node@workspace:plugins/permission-node": +"@backstage/plugin-permission-node@^0.6.5-next.3, @backstage/plugin-permission-node@workspace:plugins/permission-node": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-node@workspace:plugins/permission-node" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.2 - "@backstage/plugin-permission-common": ^0.6.4-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 express: ^4.17.1 @@ -6147,15 +6183,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-react@^0.4.5-next.1, @backstage/plugin-permission-react@workspace:plugins/permission-react": +"@backstage/plugin-permission-react@^0.4.5-next.2, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/plugin-permission-common": ^0.6.4-next.0 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 cross-fetch: ^3.1.5 @@ -6186,13 +6222,13 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-proxy-backend@^0.2.30-next.1, @backstage/plugin-proxy-backend@workspace:plugins/proxy-backend": +"@backstage/plugin-proxy-backend@^0.2.30-next.2, @backstage/plugin-proxy-backend@workspace:plugins/proxy-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@types/express": ^4.17.6 "@types/http-proxy-middleware": ^0.19.3 "@types/supertest": ^2.0.8 @@ -6212,14 +6248,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-rollbar-backend@^0.1.33-next.2, @backstage/plugin-rollbar-backend@workspace:plugins/rollbar-backend": +"@backstage/plugin-rollbar-backend@^0.1.33-next.3, @backstage/plugin-rollbar-backend@workspace:plugins/rollbar-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-rollbar-backend@workspace:plugins/rollbar-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 camelcase-keys: ^7.0.1 @@ -6238,18 +6274,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-rollbar@^0.4.9-next.2, @backstage/plugin-rollbar@workspace:plugins/rollbar": +"@backstage/plugin-rollbar@^0.4.9-next.3, @backstage/plugin-rollbar@workspace:plugins/rollbar": version: 0.0.0-use.local resolution: "@backstage/plugin-rollbar@workspace:plugins/rollbar" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6276,12 +6312,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-cookiecutter@workspace:plugins/scaffolder-backend-module-cookiecutter" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-scaffolder-backend": ^1.6.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-scaffolder-backend": ^1.6.0-next.3 "@backstage/types": ^1.0.0 "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 @@ -6295,16 +6331,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend-module-rails@^0.4.4-next.0, @backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails": +"@backstage/plugin-scaffolder-backend-module-rails@^0.4.4-next.1, @backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-rails@workspace:plugins/scaffolder-backend-module-rails" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.0 - "@backstage/plugin-scaffolder-backend": ^1.6.0-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-scaffolder-backend": ^1.6.0-next.3 "@backstage/types": ^1.0.0 "@types/command-exists": ^1.2.0 "@types/fs-extra": ^9.0.1 @@ -6321,33 +6357,33 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-yeoman@workspace:plugins/scaffolder-backend-module-yeoman" dependencies: - "@backstage/backend-common": ^0.15.1-next.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/plugin-scaffolder-backend": ^1.6.0-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-scaffolder-backend": ^1.6.0-next.3 "@backstage/types": ^1.0.0 winston: ^3.2.1 yeoman-environment: ^3.9.1 languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-backend@^1.6.0-next.0, @backstage/plugin-scaffolder-backend@^1.6.0-next.1, @backstage/plugin-scaffolder-backend@^1.6.0-next.2, @backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend": +"@backstage/plugin-scaffolder-backend@^1.6.0-next.1, @backstage/plugin-scaffolder-backend@^1.6.0-next.3, @backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend@workspace:plugins/scaffolder-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-plugin-api": ^0.1.2-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-auth-node": ^0.2.5-next.2 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 - "@backstage/plugin-catalog-node": ^1.0.2-next.1 - "@backstage/plugin-scaffolder-common": ^1.2.0-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-plugin-api": ^0.1.2-next.2 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 + "@backstage/plugin-catalog-node": ^1.1.0-next.2 + "@backstage/plugin-scaffolder-common": ^1.2.0-next.1 "@backstage/types": ^1.0.0 "@gitbeaker/core": ^35.6.0 "@gitbeaker/node": ^35.1.0 @@ -6395,37 +6431,37 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-scaffolder-common@^1.2.0-next.0, @backstage/plugin-scaffolder-common@workspace:plugins/scaffolder-common": +"@backstage/plugin-scaffolder-common@^1.2.0-next.1, @backstage/plugin-scaffolder-common@workspace:plugins/scaffolder-common": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-common@workspace:plugins/scaffolder-common" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 "@backstage/types": ^1.0.0 languageName: unknown linkType: soft -"@backstage/plugin-scaffolder@^1.6.0-next.2, @backstage/plugin-scaffolder@workspace:plugins/scaffolder": +"@backstage/plugin-scaffolder@^1.6.0-next.3, @backstage/plugin-scaffolder@workspace:plugins/scaffolder": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder@workspace:plugins/scaffolder" dependencies: - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-catalog": ^1.5.1-next.2 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-permission-react": ^0.4.5-next.1 - "@backstage/plugin-scaffolder-common": ^1.2.0-next.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/plugin-scaffolder-common": ^1.2.0-next.1 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@codemirror/language": ^6.0.0 @@ -6469,14 +6505,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend-module-elasticsearch@^1.0.2-next.1, @backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch": +"@backstage/plugin-search-backend-module-elasticsearch@^1.0.2-next.2, @backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/plugin-search-backend-node": ^1.0.2-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-search-backend-node": ^1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@elastic/elasticsearch": ^7.13.0 "@elastic/elasticsearch-mock": ^1.0.0 @@ -6491,15 +6527,15 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend-module-pg@^0.4.0-next.1, @backstage/plugin-search-backend-module-pg@workspace:plugins/search-backend-module-pg": +"@backstage/plugin-search-backend-module-pg@^0.4.0-next.2, @backstage/plugin-search-backend-module-pg@workspace:plugins/search-backend-module-pg": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-pg@workspace:plugins/search-backend-module-pg" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/plugin-search-backend-node": ^1.0.2-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-search-backend-node": ^1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 knex: ^2.0.0 lodash: ^4.17.21 @@ -6507,16 +6543,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend-node@1.0.2-next.1, @backstage/plugin-search-backend-node@^1.0.2-next.1, @backstage/plugin-search-backend-node@workspace:plugins/search-backend-node": +"@backstage/plugin-search-backend-node@1.0.2-next.2, @backstage/plugin-search-backend-node@^1.0.2-next.2, @backstage/plugin-search-backend-node@workspace:plugins/search-backend-node": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-node@workspace:plugins/search-backend-node" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-permission-common": ^0.6.4-next.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-permission-common": ^0.6.4-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@types/lunr": ^2.3.3 "@types/ndjson": ^2.0.1 @@ -6529,18 +6565,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend@^1.0.2-next.0, @backstage/plugin-search-backend@workspace:plugins/search-backend": +"@backstage/plugin-search-backend@^1.0.2-next.1, @backstage/plugin-search-backend@workspace:plugins/search-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend@workspace:plugins/search-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.1 - "@backstage/plugin-permission-common": ^0.6.4-next.0 - "@backstage/plugin-permission-node": ^0.6.5-next.1 - "@backstage/plugin-search-backend-node": ^1.0.2-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-node": ^0.6.5-next.3 + "@backstage/plugin-search-backend-node": ^1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/types": ^1.0.0 "@types/express": ^4.17.6 @@ -6605,22 +6641,22 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search@^1.0.2-next.2, @backstage/plugin-search@workspace:plugins/search": +"@backstage/plugin-search@^1.0.2-next.3, @backstage/plugin-search@workspace:plugins/search": version: 0.0.0-use.local resolution: "@backstage/plugin-search@workspace:plugins/search" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 @@ -6644,18 +6680,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-sentry@^0.4.2-next.2, @backstage/plugin-sentry@workspace:plugins/sentry": +"@backstage/plugin-sentry@^0.4.2-next.3, @backstage/plugin-sentry@workspace:plugins/sentry": version: 0.0.0-use.local resolution: "@backstage/plugin-sentry@workspace:plugins/sentry" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-table/core": ^3.1.0 "@material-ui/core": ^4.12.2 @@ -6678,16 +6714,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-shortcuts@^0.3.1-next.2, @backstage/plugin-shortcuts@workspace:plugins/shortcuts": +"@backstage/plugin-shortcuts@^0.3.1-next.3, @backstage/plugin-shortcuts@workspace:plugins/shortcuts": version: 0.0.0-use.local resolution: "@backstage/plugin-shortcuts@workspace:plugins/shortcuts" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -6714,11 +6750,11 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-sonarqube-backend@workspace:plugins/sonarqube-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@types/express": "*" "@types/supertest": ^2.0.12 express: ^4.18.1 @@ -6735,14 +6771,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-sonarqube@workspace:plugins/sonarqube" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6765,14 +6801,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-splunk-on-call@workspace:plugins/splunk-on-call" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6797,8 +6833,8 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow-backend@workspace:plugins/stack-overflow-backend" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@backstage/plugin-search-common": ^1.0.1-next.0 node-fetch: ^2.6.7 qs: ^6.9.4 @@ -6806,19 +6842,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-stack-overflow@^0.1.5-next.2, @backstage/plugin-stack-overflow@workspace:plugins/stack-overflow": +"@backstage/plugin-stack-overflow@^0.1.5-next.3, @backstage/plugin-stack-overflow@workspace:plugins/stack-overflow": version: 0.0.0-use.local resolution: "@backstage/plugin-stack-overflow@workspace:plugins/stack-overflow" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/plugin-home": ^0.4.25-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/plugin-home": ^0.4.25-next.3 "@backstage/plugin-search-common": ^1.0.1-next.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -6861,16 +6897,16 @@ __metadata: languageName: node linkType: hard -"@backstage/plugin-tech-insights-backend-module-jsonfc@^0.1.20-next.0, @backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc": +"@backstage/plugin-tech-insights-backend-module-jsonfc@^0.1.20-next.1, @backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/plugin-tech-insights-common": ^0.2.6 - "@backstage/plugin-tech-insights-node": ^0.3.4-next.0 + "@backstage/plugin-tech-insights-node": ^0.3.4-next.1 ajv: ^8.10.0 json-rules-engine: ^6.1.2 lodash: ^4.17.21 @@ -6879,20 +6915,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-tech-insights-backend@^0.5.2-next.1, @backstage/plugin-tech-insights-backend@workspace:plugins/tech-insights-backend": +"@backstage/plugin-tech-insights-backend@^0.5.2-next.2, @backstage/plugin-tech-insights-backend@workspace:plugins/tech-insights-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-insights-backend@workspace:plugins/tech-insights-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/catalog-client": ^1.0.5-next.0 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/plugin-tech-insights-common": ^0.2.6 - "@backstage/plugin-tech-insights-node": ^0.3.4-next.0 + "@backstage/plugin-tech-insights-node": ^0.3.4-next.1 "@types/express": ^4.17.6 "@types/luxon": ^3.0.0 "@types/semver": ^7.3.8 @@ -6922,14 +6958,14 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-tech-insights-node@^0.3.4-next.0, @backstage/plugin-tech-insights-node@workspace:plugins/tech-insights-node": +"@backstage/plugin-tech-insights-node@^0.3.4-next.1, @backstage/plugin-tech-insights-node@workspace:plugins/tech-insights-node": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-insights-node@workspace:plugins/tech-insights-node" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 "@backstage/plugin-tech-insights-common": ^0.2.6 "@backstage/types": ^1.0.0 "@types/luxon": ^3.0.0 @@ -6938,20 +6974,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-tech-insights@^0.3.0-next.2, @backstage/plugin-tech-insights@workspace:plugins/tech-insights": +"@backstage/plugin-tech-insights@^0.3.0-next.3, @backstage/plugin-tech-insights@workspace:plugins/tech-insights": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-insights@workspace:plugins/tech-insights" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@backstage/plugin-tech-insights-common": ^0.2.6 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -6971,16 +7007,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-tech-radar@^0.5.16-next.2, @backstage/plugin-tech-radar@workspace:plugins/tech-radar": +"@backstage/plugin-tech-radar@^0.5.16-next.3, @backstage/plugin-tech-radar@workspace:plugins/tech-radar": version: 0.0.0-use.local resolution: "@backstage/plugin-tech-radar@workspace:plugins/tech-radar" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7003,21 +7039,21 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs-addons-test-utils@^1.0.4-next.2, @backstage/plugin-techdocs-addons-test-utils@workspace:plugins/techdocs-addons-test-utils": +"@backstage/plugin-techdocs-addons-test-utils@^1.0.4-next.3, @backstage/plugin-techdocs-addons-test-utils@workspace:plugins/techdocs-addons-test-utils": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-addons-test-utils@workspace:plugins/techdocs-addons-test-utils" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-catalog": ^1.5.1-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/plugin-techdocs": ^1.3.2-next.2 - "@backstage/plugin-techdocs-react": ^1.0.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/plugin-techdocs": ^1.3.2-next.3 + "@backstage/plugin-techdocs-react": ^1.0.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 @@ -7038,23 +7074,23 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs-backend@^1.3.0-next.1, @backstage/plugin-techdocs-backend@workspace:plugins/techdocs-backend": +"@backstage/plugin-techdocs-backend@^1.3.0-next.2, @backstage/plugin-techdocs-backend@workspace:plugins/techdocs-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-backend@workspace:plugins/techdocs-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-permission-common": ^0.6.4-next.1 - "@backstage/plugin-search-backend-node": 1.0.2-next.1 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-search-backend-node": 1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 - "@backstage/plugin-techdocs-node": ^1.4.0-next.1 + "@backstage/plugin-techdocs-node": ^1.4.0-next.2 "@types/dockerode": ^3.3.0 "@types/express": ^4.17.6 dockerode: ^3.3.1 @@ -7071,20 +7107,20 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs-module-addons-contrib@^1.0.4-next.1, @backstage/plugin-techdocs-module-addons-contrib@workspace:plugins/techdocs-module-addons-contrib": +"@backstage/plugin-techdocs-module-addons-contrib@^1.0.4-next.2, @backstage/plugin-techdocs-module-addons-contrib@workspace:plugins/techdocs-module-addons-contrib": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-module-addons-contrib@workspace:plugins/techdocs-module-addons-contrib" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-techdocs-addons-test-utils": ^1.0.4-next.2 - "@backstage/plugin-techdocs-react": ^1.0.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-techdocs-addons-test-utils": ^1.0.4-next.3 + "@backstage/plugin-techdocs-react": ^1.0.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 @@ -7104,18 +7140,18 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs-node@^1.4.0-next.1, @backstage/plugin-techdocs-node@workspace:plugins/techdocs-node": +"@backstage/plugin-techdocs-node@^1.4.0-next.2, @backstage/plugin-techdocs-node@workspace:plugins/techdocs-node": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-node@workspace:plugins/techdocs-node" dependencies: "@azure/identity": ^2.0.1 "@azure/storage-blob": ^12.5.0 - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@google-cloud/storage": ^6.0.0 "@trendyol-js/openstack-swift-sdk": ^0.0.5 @@ -7141,16 +7177,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs-react@^1.0.4-next.1, @backstage/plugin-techdocs-react@workspace:plugins/techdocs-react": +"@backstage/plugin-techdocs-react@^1.0.4-next.2, @backstage/plugin-techdocs-react@workspace:plugins/techdocs-react": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs-react@workspace:plugins/techdocs-react" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@backstage/version-bridge": ^1.0.1 "@material-ui/core": ^4.12.2 @@ -7170,25 +7206,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-techdocs@^1.3.2-next.1, @backstage/plugin-techdocs@^1.3.2-next.2, @backstage/plugin-techdocs@workspace:plugins/techdocs": +"@backstage/plugin-techdocs@^1.3.2-next.3, @backstage/plugin-techdocs@workspace:plugins/techdocs": version: 0.0.0-use.local resolution: "@backstage/plugin-techdocs@workspace:plugins/techdocs" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/plugin-techdocs-react": ^1.0.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/plugin-techdocs-react": ^1.0.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7220,17 +7256,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-todo-backend@^0.1.33-next.1, @backstage/plugin-todo-backend@workspace:plugins/todo-backend": +"@backstage/plugin-todo-backend@^0.1.33-next.2, @backstage/plugin-todo-backend@workspace:plugins/todo-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-todo-backend@workspace:plugins/todo-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/integration": ^1.3.1-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/integration": ^1.3.1-next.2 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 express: ^4.17.1 @@ -7243,19 +7279,19 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-todo@^0.2.11-next.2, @backstage/plugin-todo@workspace:plugins/todo": +"@backstage/plugin-todo@^0.2.11-next.3, @backstage/plugin-todo@workspace:plugins/todo": version: 0.0.0-use.local resolution: "@backstage/plugin-todo@workspace:plugins/todo" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7273,16 +7309,16 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-user-settings@^0.4.8-next.2, @backstage/plugin-user-settings@workspace:plugins/user-settings": +"@backstage/plugin-user-settings@^0.4.8-next.3, @backstage/plugin-user-settings@workspace:plugins/user-settings": version: 0.0.0-use.local resolution: "@backstage/plugin-user-settings@workspace:plugins/user-settings" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7305,12 +7341,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-vault-backend@workspace:plugins/vault-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/backend-test-utils": ^0.1.28-next.2 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 "@types/compression": ^1.7.2 "@types/express": "*" "@types/supertest": ^2.0.8 @@ -7332,15 +7368,15 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-vault@workspace:plugins/vault" dependencies: - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7361,13 +7397,13 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-xcmetrics@workspace:plugins/xcmetrics" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/dev-utils": ^1.0.6-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 @@ -7388,28 +7424,28 @@ __metadata: languageName: unknown linkType: soft -"@backstage/release-manifests@^0.0.6-next.1, @backstage/release-manifests@workspace:packages/release-manifests": +"@backstage/release-manifests@^0.0.6-next.2, @backstage/release-manifests@workspace:packages/release-manifests": version: 0.0.0-use.local resolution: "@backstage/release-manifests@workspace:packages/release-manifests" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@types/node": ^16.0.0 cross-fetch: ^3.1.5 msw: ^0.47.0 languageName: unknown linkType: soft -"@backstage/test-utils@^1.2.0-next.1, @backstage/test-utils@^1.2.0-next.2, @backstage/test-utils@workspace:packages/test-utils": +"@backstage/test-utils@^1.2.0-next.1, @backstage/test-utils@^1.2.0-next.2, @backstage/test-utils@^1.2.0-next.3, @backstage/test-utils@workspace:packages/test-utils": version: 0.0.0-use.local resolution: "@backstage/test-utils@workspace:packages/test-utils" dependencies: - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/plugin-permission-common": ^0.6.4-next.1 - "@backstage/plugin-permission-react": ^0.4.5-next.1 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-react": ^0.4.5-next.2 "@backstage/theme": ^0.2.16 "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 @@ -9105,11 +9141,11 @@ __metadata: version: 0.0.0-use.local resolution: "@internal/plugin-todo-list-backend@workspace:plugins/example-todo-list-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 "@types/uuid": ^8.0.0 @@ -13274,12 +13310,12 @@ __metadata: version: 0.0.0-use.local resolution: "@techdocs/cli@workspace:packages/techdocs-cli" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/cli-common": ^0.1.9 - "@backstage/config": ^1.0.1 - "@backstage/plugin-techdocs-node": ^1.4.0-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 + "@backstage/config": ^1.0.2-next.0 + "@backstage/plugin-techdocs-node": ^1.4.0-next.2 "@types/commander": ^2.12.2 "@types/dockerode": ^3.3.0 "@types/fs-extra": ^9.0.6 @@ -21170,9 +21206,9 @@ __metadata: version: 0.0.0-use.local resolution: "e2e-test@workspace:packages/e2e-test" dependencies: - "@backstage/cli": ^0.19.0-next.1 - "@backstage/cli-common": ^0.1.9-next.0 - "@backstage/errors": ^1.1.0-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/cli-common": ^0.1.10-next.0 + "@backstage/errors": ^1.1.1-next.0 "@types/fs-extra": ^9.0.1 "@types/node": ^16.11.26 "@types/puppeteer": ^5.4.4 @@ -22395,60 +22431,60 @@ __metadata: version: 0.0.0-use.local resolution: "example-app@workspace:packages/app" dependencies: - "@backstage/app-defaults": ^1.0.6-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.2 - "@backstage/core-components": ^0.11.1-next.2 - "@backstage/core-plugin-api": ^1.0.6-next.2 - "@backstage/integration-react": ^1.1.4-next.1 - "@backstage/plugin-airbrake": ^0.3.9-next.2 - "@backstage/plugin-apache-airflow": ^0.2.2-next.2 - "@backstage/plugin-api-docs": ^0.8.9-next.2 - "@backstage/plugin-azure-devops": ^0.2.0-next.2 - "@backstage/plugin-badges": ^0.2.33-next.2 + "@backstage/app-defaults": ^1.0.6-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-airbrake": ^0.3.9-next.3 + "@backstage/plugin-apache-airflow": ^0.2.2-next.3 + "@backstage/plugin-api-docs": ^0.8.9-next.3 + "@backstage/plugin-azure-devops": ^0.2.0-next.3 + "@backstage/plugin-badges": ^0.2.33-next.3 "@backstage/plugin-catalog-common": ^1.0.6-next.0 - "@backstage/plugin-catalog-graph": ^0.2.21-next.1 - "@backstage/plugin-catalog-import": ^0.8.12-next.2 - "@backstage/plugin-catalog-react": ^1.1.4-next.1 - "@backstage/plugin-circleci": ^0.3.9-next.2 - "@backstage/plugin-cloudbuild": ^0.3.9-next.2 - "@backstage/plugin-code-coverage": ^0.2.2-next.2 - "@backstage/plugin-cost-insights": ^0.11.31-next.2 - "@backstage/plugin-dynatrace": ^0.2.0-next.2 - "@backstage/plugin-explore": ^0.3.40-next.2 - "@backstage/plugin-gcalendar": ^0.3.5-next.2 - "@backstage/plugin-gcp-projects": ^0.3.28-next.2 - "@backstage/plugin-github-actions": ^0.5.9-next.2 - "@backstage/plugin-gocd": ^0.1.15-next.1 - "@backstage/plugin-graphiql": ^0.2.41-next.2 - "@backstage/plugin-home": ^0.4.25-next.2 - "@backstage/plugin-jenkins": ^0.7.8-next.2 - "@backstage/plugin-kafka": ^0.3.9-next.2 - "@backstage/plugin-kubernetes": ^0.7.2-next.2 - "@backstage/plugin-lighthouse": ^0.3.9-next.2 - "@backstage/plugin-newrelic": ^0.3.27-next.2 - "@backstage/plugin-newrelic-dashboard": ^0.2.2-next.1 - "@backstage/plugin-org": ^0.5.9-next.2 - "@backstage/plugin-pagerduty": 0.5.2-next.2 - "@backstage/plugin-permission-react": ^0.4.5-next.1 - "@backstage/plugin-rollbar": ^0.4.9-next.2 - "@backstage/plugin-scaffolder": ^1.6.0-next.2 - "@backstage/plugin-search": ^1.0.2-next.2 + "@backstage/plugin-catalog-graph": ^0.2.21-next.2 + "@backstage/plugin-catalog-import": ^0.8.12-next.3 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-circleci": ^0.3.9-next.3 + "@backstage/plugin-cloudbuild": ^0.3.9-next.3 + "@backstage/plugin-code-coverage": ^0.2.2-next.3 + "@backstage/plugin-cost-insights": ^0.11.31-next.3 + "@backstage/plugin-dynatrace": ^0.2.0-next.3 + "@backstage/plugin-explore": ^0.3.40-next.3 + "@backstage/plugin-gcalendar": ^0.3.5-next.3 + "@backstage/plugin-gcp-projects": ^0.3.28-next.3 + "@backstage/plugin-github-actions": ^0.5.9-next.3 + "@backstage/plugin-gocd": ^0.1.15-next.2 + "@backstage/plugin-graphiql": ^0.2.41-next.3 + "@backstage/plugin-home": ^0.4.25-next.3 + "@backstage/plugin-jenkins": ^0.7.8-next.3 + "@backstage/plugin-kafka": ^0.3.9-next.3 + "@backstage/plugin-kubernetes": ^0.7.2-next.3 + "@backstage/plugin-lighthouse": ^0.3.9-next.3 + "@backstage/plugin-newrelic": ^0.3.27-next.3 + "@backstage/plugin-newrelic-dashboard": ^0.2.2-next.2 + "@backstage/plugin-org": ^0.5.9-next.3 + "@backstage/plugin-pagerduty": 0.5.2-next.3 + "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/plugin-rollbar": ^0.4.9-next.3 + "@backstage/plugin-scaffolder": ^1.6.0-next.3 + "@backstage/plugin-search": ^1.0.2-next.3 "@backstage/plugin-search-common": ^1.0.1-next.0 "@backstage/plugin-search-react": ^1.1.0-next.2 - "@backstage/plugin-sentry": ^0.4.2-next.2 - "@backstage/plugin-shortcuts": ^0.3.1-next.2 - "@backstage/plugin-stack-overflow": ^0.1.5-next.2 - "@backstage/plugin-tech-insights": ^0.3.0-next.2 - "@backstage/plugin-tech-radar": ^0.5.16-next.2 - "@backstage/plugin-techdocs": ^1.3.2-next.2 - "@backstage/plugin-techdocs-module-addons-contrib": ^1.0.4-next.1 - "@backstage/plugin-techdocs-react": ^1.0.4-next.1 - "@backstage/plugin-todo": ^0.2.11-next.2 - "@backstage/plugin-user-settings": ^0.4.8-next.2 - "@backstage/test-utils": ^1.2.0-next.2 + "@backstage/plugin-sentry": ^0.4.2-next.3 + "@backstage/plugin-shortcuts": ^0.3.1-next.3 + "@backstage/plugin-stack-overflow": ^0.1.5-next.3 + "@backstage/plugin-tech-insights": ^0.3.0-next.3 + "@backstage/plugin-tech-radar": ^0.5.16-next.3 + "@backstage/plugin-techdocs": ^1.3.2-next.3 + "@backstage/plugin-techdocs-module-addons-contrib": ^1.0.4-next.2 + "@backstage/plugin-techdocs-react": ^1.0.4-next.2 + "@backstage/plugin-todo": ^0.2.11-next.3 + "@backstage/plugin-user-settings": ^0.4.8-next.3 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@internal/plugin-catalog-customized": 0.0.2-next.0 "@material-ui/core": ^4.12.2 @@ -22499,41 +22535,41 @@ __metadata: version: 0.0.0-use.local resolution: "example-backend@workspace:packages/backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.2 - "@backstage/backend-tasks": ^0.3.5-next.0 - "@backstage/catalog-client": ^1.0.5-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.2 - "@backstage/config": ^1.0.1 - "@backstage/integration": ^1.3.1-next.1 - "@backstage/plugin-app-backend": ^0.3.36-next.2 - "@backstage/plugin-auth-backend": ^0.16.0-next.2 - "@backstage/plugin-auth-node": ^0.2.5-next.2 - "@backstage/plugin-azure-devops-backend": ^0.3.15-next.1 - "@backstage/plugin-badges-backend": ^0.1.30-next.0 - "@backstage/plugin-catalog-backend": ^1.4.0-next.2 - "@backstage/plugin-code-coverage-backend": ^0.2.2-next.1 - "@backstage/plugin-graphql-backend": ^0.1.26-next.2 - "@backstage/plugin-jenkins-backend": ^0.1.26-next.2 - "@backstage/plugin-kafka-backend": ^0.2.29-next.0 - "@backstage/plugin-kubernetes-backend": ^0.7.2-next.2 - "@backstage/plugin-permission-backend": ^0.5.11-next.1 - "@backstage/plugin-permission-common": ^0.6.4-next.1 - "@backstage/plugin-permission-node": ^0.6.5-next.2 - "@backstage/plugin-proxy-backend": ^0.2.30-next.1 - "@backstage/plugin-rollbar-backend": ^0.1.33-next.2 - "@backstage/plugin-scaffolder-backend": ^1.6.0-next.2 - "@backstage/plugin-scaffolder-backend-module-rails": ^0.4.4-next.0 - "@backstage/plugin-search-backend": ^1.0.2-next.0 - "@backstage/plugin-search-backend-module-elasticsearch": ^1.0.2-next.1 - "@backstage/plugin-search-backend-module-pg": ^0.4.0-next.1 - "@backstage/plugin-search-backend-node": ^1.0.2-next.1 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-tasks": ^0.3.5-next.1 + "@backstage/catalog-client": ^1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/integration": ^1.3.1-next.2 + "@backstage/plugin-app-backend": ^0.3.36-next.3 + "@backstage/plugin-auth-backend": ^0.16.0-next.3 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-azure-devops-backend": ^0.3.15-next.2 + "@backstage/plugin-badges-backend": ^0.1.30-next.1 + "@backstage/plugin-catalog-backend": ^1.4.0-next.3 + "@backstage/plugin-code-coverage-backend": ^0.2.2-next.2 + "@backstage/plugin-graphql-backend": ^0.1.26-next.3 + "@backstage/plugin-jenkins-backend": ^0.1.26-next.3 + "@backstage/plugin-kafka-backend": ^0.2.29-next.1 + "@backstage/plugin-kubernetes-backend": ^0.7.2-next.3 + "@backstage/plugin-permission-backend": ^0.5.11-next.2 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-node": ^0.6.5-next.3 + "@backstage/plugin-proxy-backend": ^0.2.30-next.2 + "@backstage/plugin-rollbar-backend": ^0.1.33-next.3 + "@backstage/plugin-scaffolder-backend": ^1.6.0-next.3 + "@backstage/plugin-scaffolder-backend-module-rails": ^0.4.4-next.1 + "@backstage/plugin-search-backend": ^1.0.2-next.1 + "@backstage/plugin-search-backend-module-elasticsearch": ^1.0.2-next.2 + "@backstage/plugin-search-backend-module-pg": ^0.4.0-next.2 + "@backstage/plugin-search-backend-node": ^1.0.2-next.2 "@backstage/plugin-search-common": ^1.0.1-next.0 - "@backstage/plugin-tech-insights-backend": ^0.5.2-next.1 - "@backstage/plugin-tech-insights-backend-module-jsonfc": ^0.1.20-next.0 - "@backstage/plugin-tech-insights-node": ^0.3.4-next.0 - "@backstage/plugin-techdocs-backend": ^1.3.0-next.1 - "@backstage/plugin-todo-backend": ^0.1.33-next.1 + "@backstage/plugin-tech-insights-backend": ^0.5.2-next.2 + "@backstage/plugin-tech-insights-backend-module-jsonfc": ^0.1.20-next.1 + "@backstage/plugin-tech-insights-node": ^0.3.4-next.1 + "@backstage/plugin-techdocs-backend": ^1.3.0-next.2 + "@backstage/plugin-todo-backend": ^0.1.33-next.2 "@gitbeaker/node": ^35.1.0 "@octokit/rest": ^19.0.3 "@types/dockerode": ^3.3.0 @@ -38179,18 +38215,18 @@ __metadata: version: 0.0.0-use.local resolution: "techdocs-cli-embedded-app@workspace:packages/techdocs-cli-embedded-app" dependencies: - "@backstage/app-defaults": ^1.0.6-next.1 - "@backstage/catalog-model": ^1.1.0 - "@backstage/cli": ^0.19.0-next.1 - "@backstage/config": ^1.0.1 - "@backstage/core-app-api": ^1.1.0-next.1 - "@backstage/core-components": ^0.11.1-next.1 - "@backstage/core-plugin-api": ^1.0.6-next.1 - "@backstage/integration-react": ^1.1.4-next.0 - "@backstage/plugin-catalog": ^1.5.1-next.1 - "@backstage/plugin-techdocs": ^1.3.2-next.1 - "@backstage/plugin-techdocs-react": ^1.0.4-next.1 - "@backstage/test-utils": ^1.2.0-next.1 + "@backstage/app-defaults": ^1.0.6-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/integration-react": ^1.1.4-next.2 + "@backstage/plugin-catalog": ^1.5.1-next.3 + "@backstage/plugin-techdocs": ^1.3.2-next.3 + "@backstage/plugin-techdocs-react": ^1.0.4-next.2 + "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 "@material-ui/core": ^4.11.0 "@material-ui/icons": ^4.9.1 From 709f4683301be50e66024f81698f6404b8d08b87 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Tue, 13 Sep 2022 10:21:50 +0200 Subject: [PATCH 18/95] backend-common: wrap branch command Signed-off-by: Magnus Persson --- .changeset/smooth-camels-melt.md | 5 +++++ packages/backend-common/api-report.md | 2 ++ packages/backend-common/src/scm/git.test.ts | 16 ++++++++++++++++ packages/backend-common/src/scm/git.ts | 7 +++++++ 4 files changed, 30 insertions(+) create mode 100644 .changeset/smooth-camels-melt.md diff --git a/.changeset/smooth-camels-melt.md b/.changeset/smooth-camels-melt.md new file mode 100644 index 0000000000..bd816827a4 --- /dev/null +++ b/.changeset/smooth-camels-melt.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +The `branch` command has been added to the `Git` isomorphic-git wrapper. diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 40bd885fe8..600e3edef8 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -342,6 +342,8 @@ export class Git { force?: boolean; }): Promise; // (undocumented) + branch(options: { dir: string; ref: string }): Promise; + // (undocumented) checkout(options: { dir: string; ref: string }): Promise; clone(options: { url: string; diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index e9c66a896e..fdd3c7dbc8 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -95,6 +95,22 @@ describe('Git', () => { }); }); + describe('branch', () => { + it('should call isomorphic-git with the correct arguments', async () => { + const git = Git.fromAuth({}); + const dir = 'mockdirectory'; + const ref = 'master'; + + await git.branch({ dir, ref }); + + expect(isomorphic.branch).toHaveBeenCalledWith({ + fs, + dir, + ref, + }); + }); + }); + describe('commit', () => { it('should call isomorphic-git with the correct arguments', async () => { const git = Git.fromAuth({}); diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 8a72c7af89..0c9252cb64 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -94,6 +94,13 @@ export class Git { return git.checkout({ fs, dir, ref }); } + async branch(options: { dir: string; ref: string }): Promise { + const { dir, ref } = options; + this.config.logger?.info(`Creating branch {dir=${dir},ref=${ref}`); + + return git.branch({ fs, dir, ref }); + } + async commit(options: { dir: string; message: string; From 3924292cf3eea19e765fffb5bd767dc9e9da0967 Mon Sep 17 00:00:00 2001 From: bnechyporenko Date: Tue, 13 Sep 2022 12:29:29 +0200 Subject: [PATCH 19/95] Incorporated the feedback Signed-off-by: bnechyporenko --- .changeset/hungry-llamas-tie.md | 1 - .../src/lib/resolvers/CatalogAuthResolverContext.ts | 2 +- .../src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.changeset/hungry-llamas-tie.md b/.changeset/hungry-llamas-tie.md index c4848b50ef..0f3be39c3f 100644 --- a/.changeset/hungry-llamas-tie.md +++ b/.changeset/hungry-llamas-tie.md @@ -1,5 +1,4 @@ --- -'@backstage/plugin-auth-backend': patch '@backstage/plugin-scaffolder-backend': patch --- diff --git a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts index c62c0737d8..cbc2439563 100644 --- a/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts +++ b/plugins/auth-backend/src/lib/resolvers/CatalogAuthResolverContext.ts @@ -27,7 +27,7 @@ import { ConflictError, InputError, NotFoundError } from '@backstage/errors'; import { Logger } from 'winston'; import { TokenIssuer, TokenParams } from '../../identity/types'; import { AuthResolverContext } from '../../providers'; -import { AuthResolverCatalogUserQuery } from '../../providers'; +import { AuthResolverCatalogUserQuery } from '../../providers/types'; import { CatalogIdentityClient } from '../catalog'; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 5af26bfea3..8745b7afdf 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -66,7 +66,7 @@ describe('DefaultWorkflowRunner', () => { }); beforeEach(() => { - winston.format.simple(); // put logform the required cache before mocking fs + winston.format.simple(); // put logform in the require.cache before mocking fs mockFs({ '/tmp': mockFs.directory(), ...realFiles, From 3bced8687cfcedf048bafb49d519186b82d66eb4 Mon Sep 17 00:00:00 2001 From: Samba siva Tiyyagura <40207674+stiyyagura0901@users.noreply.github.com> Date: Wed, 14 Sep 2022 14:47:32 -0400 Subject: [PATCH 20/95] Update index.md Fix a small typo Signed-off-by: Samba siva Tiyyagura <40207674+stiyyagura0901@users.noreply.github.com> --- docs/auth/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/auth/index.md b/docs/auth/index.md index 8d303c776d..ab04d3ed87 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -65,7 +65,7 @@ the local `auth.environment` setting will be selected. > and access to a Backstage Identity Token, which can be passed to backend > plugins. -Using an authentication provide for sign-in is something you need to configure +Using an authentication provider for sign-in is something you need to configure both in the frontend app, as well as the `auth` backend plugin. For information on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md). The rest of this section will focus on how to configure sign-in for the frontend app. From a98f5d4c212283eae991dd287569241e8b9675a5 Mon Sep 17 00:00:00 2001 From: Jake Crews Date: Thu, 15 Sep 2022 08:51:02 -0500 Subject: [PATCH 21/95] Add the ability to pass custom defaults to createGitlabApi constructor Signed-off-by: Jake Crews --- .changeset/wicked-spies-draw.md | 5 +++++ plugins/cicd-statistics-module-gitlab/src/api/gitlab.ts | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .changeset/wicked-spies-draw.md diff --git a/.changeset/wicked-spies-draw.md b/.changeset/wicked-spies-draw.md new file mode 100644 index 0000000000..3b92e394d0 --- /dev/null +++ b/.changeset/wicked-spies-draw.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cicd-statistics-module-gitlab': patch +--- + +add the ability to add cicd default options to createGitlabApi constructor diff --git a/plugins/cicd-statistics-module-gitlab/src/api/gitlab.ts b/plugins/cicd-statistics-module-gitlab/src/api/gitlab.ts index 7439d1800c..5e4384fe88 100644 --- a/plugins/cicd-statistics-module-gitlab/src/api/gitlab.ts +++ b/plugins/cicd-statistics-module-gitlab/src/api/gitlab.ts @@ -18,6 +18,7 @@ import { CicdStatisticsApi, CicdState, CicdConfiguration, + CicdDefaults, Build, FetchBuildsOptions, Stage, @@ -47,9 +48,14 @@ export type GitlabClient = { */ export class CicdStatisticsApiGitlab implements CicdStatisticsApi { readonly #gitLabAuthApi: OAuthApi; + readonly #cicdDefaults: Partial; - constructor(gitLabAuthApi: OAuthApi) { + constructor( + gitLabAuthApi: OAuthApi, + cicdDefaults: Partial = {}, + ) { this.#gitLabAuthApi = gitLabAuthApi; + this.#cicdDefaults = cicdDefaults; } public async createGitlabApi( @@ -154,6 +160,7 @@ export class CicdStatisticsApiGitlab implements CicdStatisticsApi { 'expired', 'unknown', ] as const, + defaults: this.#cicdDefaults, }; } } From f493a9efcc639107a313db2f74cc5f62cded4a88 Mon Sep 17 00:00:00 2001 From: Jake Crews Date: Thu, 15 Sep 2022 09:47:05 -0500 Subject: [PATCH 22/95] Fix documentation errors Signed-off-by: Jake Crews --- .changeset/wicked-spies-draw.md | 2 +- plugins/cicd-statistics-module-gitlab/README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.changeset/wicked-spies-draw.md b/.changeset/wicked-spies-draw.md index 3b92e394d0..399f70e062 100644 --- a/.changeset/wicked-spies-draw.md +++ b/.changeset/wicked-spies-draw.md @@ -2,4 +2,4 @@ '@backstage/plugin-cicd-statistics-module-gitlab': patch --- -add the ability to add cicd default options to createGitlabApi constructor +add the ability to add CICD default options to createGitlabApi constructor diff --git a/plugins/cicd-statistics-module-gitlab/README.md b/plugins/cicd-statistics-module-gitlab/README.md index 0b11f6950a..392bd0e937 100644 --- a/plugins/cicd-statistics-module-gitlab/README.md +++ b/plugins/cicd-statistics-module-gitlab/README.md @@ -7,6 +7,7 @@ This is an extension module to the `cicd-statistics` plugin, providing a `CicdSt 1. Install the `cicd-statistics` and `cicd-statistics-module-gitlab` plugins in the `app` package. 2. Configure your ApiFactory: + - You can optionally pass in a second argument to `CicdStatisticsApiGitlab` of type [CicdDefaults](https://github.com/backstage/backstage/blob/2881c53cb383bf127c150f837f37fe535d8cf97b/plugins/cicd-statistics/src/apis/types.ts#L179) to alter the default CICD UI configuration ```tsx // packages/app/src/apis.ts From b31ffb0067319258697c6668679979116791e21e Mon Sep 17 00:00:00 2001 From: Jake Crews Date: Thu, 15 Sep 2022 09:58:12 -0500 Subject: [PATCH 23/95] api report generation Signed-off-by: Jake Crews --- plugins/cicd-statistics-module-gitlab/api-report.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/cicd-statistics-module-gitlab/api-report.md b/plugins/cicd-statistics-module-gitlab/api-report.md index 5e07255f54..a0364afa31 100644 --- a/plugins/cicd-statistics-module-gitlab/api-report.md +++ b/plugins/cicd-statistics-module-gitlab/api-report.md @@ -4,6 +4,7 @@ ```ts import { CicdConfiguration } from '@backstage/plugin-cicd-statistics'; +import { CicdDefaults } from '@backstage/plugin-cicd-statistics'; import { CicdState } from '@backstage/plugin-cicd-statistics'; import { CicdStatisticsApi } from '@backstage/plugin-cicd-statistics'; import { Entity } from '@backstage/catalog-model'; @@ -13,7 +14,7 @@ import { OAuthApi } from '@backstage/core-plugin-api'; // @public export class CicdStatisticsApiGitlab implements CicdStatisticsApi { - constructor(gitLabAuthApi: OAuthApi); + constructor(gitLabAuthApi: OAuthApi, cicdDefaults?: Partial); // (undocumented) createGitlabApi(entity: Entity, scopes: string[]): Promise; // (undocumented) From 0fbd20aa7efab51412e0619af82c3dbc62e634a3 Mon Sep 17 00:00:00 2001 From: Tim Jacomb <21194782+timja@users.noreply.github.com> Date: Thu, 15 Sep 2022 16:35:34 +0100 Subject: [PATCH 24/95] Update Dockerfile Signed-off-by: Tim Jacomb <21194782+timja@users.noreply.github.com> --- packages/backend/Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 7ed0121467..21ff07deb4 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -19,15 +19,17 @@ RUN apt-get update && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. -USER node WORKDIR /app +RUN chown node:node /app +USER node + # This switches many Node.js dependencies to production mode. ENV NODE_ENV production # Copy over Yarn 3 configuration, release, and plugins -COPY .yarn ./.yarn -COPY .yarnrc.yml ./ +COPY --chown=node:node .yarn ./.yarn +COPY --chown=node:node .yarnrc.yml ./ # Copy repo skeleton first, to avoid unnecessary docker cache invalidation. # The skeleton contains the package.json of each package in the monorepo, From b87a88776d168dc039957ca32adda8ecd9f54b80 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Thu, 15 Sep 2022 21:59:57 -0400 Subject: [PATCH 25/95] (feat): kubernetes add new backend endpoints to api interface Signed-off-by: Matthew Clarke --- .../src/service/KubernetesFanOutHandler.ts | 2 +- plugins/kubernetes-backend/src/types/types.ts | 7 +---- plugins/kubernetes-common/src/types.ts | 7 +++++ .../src/api/KubernetesBackendClient.ts | 30 ++++++++++++++++--- plugins/kubernetes/src/api/types.ts | 12 ++++++++ 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 7fcc9836a3..23163d1004 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -25,7 +25,6 @@ import { FetchResponseWrapper, ObjectToFetch, CustomResource, - CustomResourceMatcher, CustomResourcesByEntity, KubernetesObjectsByEntity, } from '../types/types'; @@ -40,6 +39,7 @@ import { ObjectsByEntityResponse, PodFetchResponse, KubernetesRequestAuth, + CustomResourceMatcher, } from '@backstage/plugin-kubernetes-common'; import { ContainerStatus, diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 33fde70b24..5ddfe7367d 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -18,6 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; import type { JsonObject } from '@backstage/types'; import type { + CustomResourceMatcher, FetchResponse, KubernetesFetchError, KubernetesRequestAuth, @@ -86,12 +87,6 @@ export interface CustomResource extends ObjectToFetch { objectType: 'customresources'; } -/** - * - * @alpha - */ -export type CustomResourceMatcher = Omit; - /** * * @alpha diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index 830c32c32c..07378ae688 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -39,6 +39,13 @@ export interface KubernetesRequestAuth { }; } +/** @public */ +export interface CustomResourceMatcher { + group: string; + apiVersion: string; + plural: string; +} + /** @public */ export interface KubernetesRequestBody { auth?: KubernetesRequestAuth; diff --git a/plugins/kubernetes/src/api/KubernetesBackendClient.ts b/plugins/kubernetes/src/api/KubernetesBackendClient.ts index 209f5f950d..04f4624b24 100644 --- a/plugins/kubernetes/src/api/KubernetesBackendClient.ts +++ b/plugins/kubernetes/src/api/KubernetesBackendClient.ts @@ -16,10 +16,13 @@ import { KubernetesApi } from './types'; import { + KubernetesRequestAuth, KubernetesRequestBody, ObjectsByEntityResponse, + CustomResourceMatcher, } from '@backstage/plugin-kubernetes-common'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; export class KubernetesBackendClient implements KubernetesApi { private readonly discoveryApi: DiscoveryApi; @@ -51,10 +54,7 @@ export class KubernetesBackendClient implements KubernetesApi { return await response.json(); } - private async postRequired( - path: string, - requestBody: KubernetesRequestBody, - ): Promise { + private async postRequired(path: string, requestBody: any): Promise { const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}${path}`; const { token: idToken } = await this.identityApi.getCredentials(); const response = await fetch(url, { @@ -78,6 +78,28 @@ export class KubernetesBackendClient implements KubernetesApi { ); } + async getWorkloadsByEntity( + auth: KubernetesRequestAuth, + entity: Entity, + ): Promise { + return await this.postRequired('/resources/workloads/query', { + auth, + entityRef: stringifyEntityRef(entity), + }); + } + + async getCustomObjectsByEntity( + auth: KubernetesRequestAuth, + customResources: CustomResourceMatcher[], + entity: Entity, + ): Promise { + return await this.postRequired(`/resources/custom/query`, { + entityRef: stringifyEntityRef(entity), + auth, + customResources, + }); + } + async getClusters(): Promise<{ name: string; authProvider: string }[]> { const { token: idToken } = await this.identityApi.getCredentials(); const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}/clusters`; diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes/src/api/types.ts index 7c5943a6eb..b7e3f9fd49 100644 --- a/plugins/kubernetes/src/api/types.ts +++ b/plugins/kubernetes/src/api/types.ts @@ -15,10 +15,13 @@ */ import { + KubernetesRequestAuth, KubernetesRequestBody, ObjectsByEntityResponse, + CustomResourceMatcher, } from '@backstage/plugin-kubernetes-common'; import { createApiRef } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; export const kubernetesApiRef = createApiRef({ id: 'plugin.kubernetes.service', @@ -35,4 +38,13 @@ export interface KubernetesApi { oidcTokenProvider?: string | undefined; }[] >; + getWorkloadsByEntity( + auth: KubernetesRequestAuth, + entity: Entity, + ): Promise; + getCustomObjectsByEntity( + auth: KubernetesRequestAuth, + customResources: CustomResourceMatcher[], + entity: Entity, + ): Promise; } From 29dd35cdcb9d504f7c744804e7be5e777e7f1424 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Thu, 15 Sep 2022 22:03:09 -0400 Subject: [PATCH 26/95] update api report Signed-off-by: Matthew Clarke --- plugins/kubernetes-backend/api-report.md | 4 +--- plugins/kubernetes-common/api-report.md | 10 ++++++++++ plugins/kubernetes/api-report.md | 24 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index f97a0fd032..4219387819 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -8,6 +8,7 @@ import { Config } from '@backstage/config'; import { CoreV1Api } from '@kubernetes/client-node'; import { Credentials } from 'aws-sdk'; import { CustomObjectsApi } from '@kubernetes/client-node'; +import type { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { Duration } from 'luxon'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; @@ -101,9 +102,6 @@ export interface CustomResource extends ObjectToFetch { objectType: 'customresources'; } -// @alpha (undocumented) -export type CustomResourceMatcher = Omit; - // @alpha (undocumented) export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { // (undocumented) diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index ef36d5ce28..9485bd0294 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -97,6 +97,16 @@ export interface CustomResourceFetchResponse { type: 'customresources'; } +// @public (undocumented) +export interface CustomResourceMatcher { + // (undocumented) + apiVersion: string; + // (undocumented) + group: string; + // (undocumented) + plural: string; +} + // @public (undocumented) export interface DaemonSetsFetchResponse { // (undocumented) diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 81ce386200..98ca4e4725 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -10,10 +10,12 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; import { ClusterObjects } from '@backstage/plugin-kubernetes-common'; +import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; import type { JsonObject } from '@backstage/types'; +import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; @@ -245,9 +247,20 @@ export interface KubernetesApi { }[] >; // (undocumented) + getCustomObjectsByEntity( + auth: KubernetesRequestAuth, + customResources: CustomResourceMatcher[], + entity: Entity, + ): Promise; + // (undocumented) getObjectsByEntity( requestBody: KubernetesRequestBody, ): Promise; + // (undocumented) + getWorkloadsByEntity( + auth: KubernetesRequestAuth, + entity: Entity, + ): Promise; } // Warning: (ae-missing-release-tag) "kubernetesApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -304,9 +317,20 @@ export class KubernetesBackendClient implements KubernetesApi { }[] >; // (undocumented) + getCustomObjectsByEntity( + auth: KubernetesRequestAuth, + customResources: CustomResourceMatcher[], + entity: Entity, + ): Promise; + // (undocumented) getObjectsByEntity( requestBody: KubernetesRequestBody, ): Promise; + // (undocumented) + getWorkloadsByEntity( + auth: KubernetesRequestAuth, + entity: Entity, + ): Promise; } // Warning: (ae-forgotten-export) The symbol "KubernetesContentProps" needs to be exported by the entry point index.d.ts From 0768d6dece0706b37218a2e08058bf7dd0a8f693 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Thu, 15 Sep 2022 22:04:31 -0400 Subject: [PATCH 27/95] changeset Signed-off-by: Matthew Clarke --- .changeset/poor-lobsters-wonder.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/poor-lobsters-wonder.md diff --git a/.changeset/poor-lobsters-wonder.md b/.changeset/poor-lobsters-wonder.md new file mode 100644 index 0000000000..c0adea235f --- /dev/null +++ b/.changeset/poor-lobsters-wonder.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-common': patch +--- + +add new kubernetes backend endpoints to kubernetes backend client From 3da0c9a1812a92e6d0948a88e8c2306097561574 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Thu, 15 Sep 2022 22:10:42 -0400 Subject: [PATCH 28/95] update mock Signed-off-by: Matthew Clarke --- plugins/kubernetes/dev/index.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index 068f26b7f5..6a02540604 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -24,7 +24,9 @@ import { KubernetesApi, } from '../src'; import { + CustomResourceMatcher, FetchResponse, + KubernetesRequestAuth, ObjectsByEntityResponse, } from '@backstage/plugin-kubernetes-common'; import fixture1 from '../src/__fixtures__/1-deployments.json'; @@ -59,6 +61,19 @@ class MockKubernetesClient implements KubernetesApi { ({ type: type.toLocaleLowerCase('en-US'), resources } as FetchResponse), ); } + async getWorkloadsByEntity( + _auth: KubernetesRequestAuth, + _entity: Entity, + ): Promise { + throw new Error('Method not implemented.'); + } + async getCustomObjectsByEntity( + _auth: KubernetesRequestAuth, + _customResources: CustomResourceMatcher[], + entity: Entity, + ): Promise { + throw new Error('Method not implemented.'); + } async getObjectsByEntity(): Promise { return { From 5eb54be2ac56af8765e18def149cefe09f0f920e Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Thu, 15 Sep 2022 22:15:26 -0400 Subject: [PATCH 29/95] typo Signed-off-by: Matthew Clarke --- plugins/kubernetes/dev/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index 6a02540604..3dd0557ae1 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -70,7 +70,7 @@ class MockKubernetesClient implements KubernetesApi { async getCustomObjectsByEntity( _auth: KubernetesRequestAuth, _customResources: CustomResourceMatcher[], - entity: Entity, + _entity: Entity, ): Promise { throw new Error('Method not implemented.'); } From e55d855a6ba1e754e7c99e8bd405428696c2c06d Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Fri, 16 Sep 2022 09:40:25 +0100 Subject: [PATCH 30/95] Fix Jenkins plugin not working at all Signed-off-by: Tim Jacomb --- .changeset/stale-paws-dance.md | 5 +++++ plugins/jenkins-backend/src/service/jenkinsApi.ts | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 .changeset/stale-paws-dance.md diff --git a/.changeset/stale-paws-dance.md b/.changeset/stale-paws-dance.md new file mode 100644 index 0000000000..2745faea1c --- /dev/null +++ b/.changeset/stale-paws-dance.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins-backend': patch +--- + +Jenkins plugin works again diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index ae2fa0f7b5..18a79a2ffe 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -15,7 +15,7 @@ */ import type { JenkinsInfo } from './jenkinsInfoProvider'; -import jenkins from 'jenkins'; +import Jenkins from 'jenkins'; import type { BackstageBuild, BackstageProject, @@ -177,12 +177,12 @@ export class JenkinsApiImpl { private static async getClient(jenkinsInfo: JenkinsInfo) { // The typings for the jenkins library are out of date so just cast to any - return jenkins({ + return new (Jenkins as any)({ baseUrl: jenkinsInfo.baseUrl, headers: jenkinsInfo.headers, promisify: true, crumbIssuer: jenkinsInfo.crumbIssuer, - }) as any; + }); } private augmentProject(project: JenkinsProject): BackstageProject { From a966ed8385324dde95de2a17041bee046ebb7e6e Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Fri, 16 Sep 2022 10:47:29 +0100 Subject: [PATCH 31/95] Unwrap error message when getting projects in Jenkins plugin Signed-off-by: Tim Jacomb --- .changeset/ninety-knives-knock.md | 5 +++++ .../jenkins-backend/src/service/jenkinsApi.ts | 2 +- plugins/jenkins-backend/src/service/router.ts | 20 +++++++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 .changeset/ninety-knives-knock.md diff --git a/.changeset/ninety-knives-knock.md b/.changeset/ninety-knives-knock.md new file mode 100644 index 0000000000..19797e472c --- /dev/null +++ b/.changeset/ninety-knives-knock.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-jenkins-backend': patch +--- + +Unwrap error message when getting projects diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index ae2fa0f7b5..37aaf0ac3b 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -100,7 +100,7 @@ export class JenkinsApiImpl { // Filter only be the information we need, instead of loading all fields. // Limit to only show the latest build for each job and only load 50 jobs // at all. - // Whitespaces are only included for readablity here and stripped out + // Whitespaces are only included for readability here and stripped out // before sending to Jenkins tree: JenkinsApiImpl.jobsTreeSpec.replace(/\s/g, ''), }); diff --git a/plugins/jenkins-backend/src/service/router.ts b/plugins/jenkins-backend/src/service/router.ts index bc0e978396..395efffb9c 100644 --- a/plugins/jenkins-backend/src/service/router.ts +++ b/plugins/jenkins-backend/src/service/router.ts @@ -27,6 +27,7 @@ import { } from '@backstage/plugin-permission-common'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { stringifyEntityRef } from '@backstage/catalog-model'; +import { stringifyError } from "@backstage/errors"; /** @public */ export interface RouterOptions { @@ -90,11 +91,22 @@ export async function createRouter( }, backstageToken: token, }); - const projects = await jenkinsApi.getProjects(jenkinsInfo, branches); - response.json({ - projects: projects, - }); + + try { + const projects = await jenkinsApi.getProjects(jenkinsInfo, branches); + + response.json({ + projects: projects, + }); + } catch (err) { + // Promise.any, used in the getProjects call returns an Aggregate error message with a useless error message 'AggregateError: All promises were rejected' + // extract useful information ourselves + if (err.errors) { + throw new Error(`Unable to fetch projects, for ${jenkinsInfo.jobFullName}: ${stringifyError(err.errors)}`) + } + throw err + } }, ); From d3737da3377da376b0b82c9d884cc656f5455292 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Sat, 2 Jul 2022 00:00:52 -0400 Subject: [PATCH 32/95] feat(playlists): implement playlist plugin Signed-off-by: Phil Kuang --- .changeset/calm-snakes-tap.md | 5 + .changeset/nice-ducks-smile.md | 7 + .changeset/purple-chicken-kneel.md | 5 + app-config.yaml | 3 + microsite/data/plugins/playlist.yaml | 9 + microsite/static/img/playlist-logo.png | Bin 0 -> 14734 bytes packages/app/package.json | 1 + packages/app/src/App.tsx | 2 + packages/app/src/components/Root/Root.tsx | 2 + .../app/src/components/catalog/EntityPage.tsx | 12 + packages/backend/package.json | 1 + packages/backend/src/index.ts | 3 + packages/backend/src/plugins/permission.ts | 25 +- packages/backend/src/plugins/playlist.ts | 37 ++ packages/backend/src/types.ts | 7 +- packages/core-components/api-report.md | 27 + .../src/components/Table/Table.tsx | 5 + .../HeaderActionMenu/HeaderActionMenu.tsx | 15 +- .../src/layout/HeaderActionMenu/index.ts | 4 + packages/core-components/src/layout/index.ts | 1 + plugins/playlist-backend/.eslintrc.js | 1 + plugins/playlist-backend/README.md | 93 ++++ plugins/playlist-backend/api-report.md | 93 ++++ .../migrations/20220701011329_init.js | 60 ++ plugins/playlist-backend/package.json | 52 ++ plugins/playlist-backend/src/index.ts | 28 + .../DefaultPlaylistPermissionPolicy.test.ts | 135 +++++ .../DefaultPlaylistPermissionPolicy.ts | 90 +++ .../src/permissions/conditions.ts | 44 ++ .../playlist-backend/src/permissions/index.ts | 19 + .../playlist-backend/src/permissions/rules.ts | 54 ++ plugins/playlist-backend/src/run.ts | 33 ++ .../src/service/DatabaseHandler.test.ts | 349 ++++++++++++ .../src/service/DatabaseHandler.ts | 278 ++++++++++ .../src/service/ListPlaylistsFilter.test.ts | 95 ++++ .../src/service/ListPlaylistsFilter.ts | 101 ++++ plugins/playlist-backend/src/service/index.ts | 21 + .../src/service/router.test.ts | 511 ++++++++++++++++++ .../playlist-backend/src/service/router.ts | 232 ++++++++ .../src/service/standaloneServer.ts | 90 +++ plugins/playlist-backend/src/setupTests.ts | 17 + plugins/playlist-common/.eslintrc.js | 1 + plugins/playlist-common/README.md | 3 + plugins/playlist-common/api-report.md | 36 ++ plugins/playlist-common/package.json | 34 ++ plugins/playlist-common/src/index.ts | 24 + plugins/playlist-common/src/permissions.ts | 62 +++ plugins/playlist-common/src/setupTests.ts | 16 + plugins/playlist-common/src/types.ts | 35 ++ plugins/playlist/.eslintrc.js | 1 + plugins/playlist/README.md | 128 +++++ plugins/playlist/api-report.md | 106 ++++ .../playlist/dev/index.tsx | 20 +- plugins/playlist/package.json | 67 +++ plugins/playlist/src/api/PlaylistApi.ts | 75 +++ .../playlist/src/api/PlaylistClient.test.ts | 272 ++++++++++ plugins/playlist/src/api/PlaylistClient.ts | 198 +++++++ plugins/playlist/src/api/index.ts | 18 + .../CreatePlaylistButton.test.tsx | 142 +++++ .../CreatePlaylistButton.tsx | 87 +++ .../components/CreatePlaylistButton/index.ts | 17 + .../EntityPlaylistDialog.test.tsx | 200 +++++++ .../EntityPlaylistDialog.tsx | 256 +++++++++ .../components/EntityPlaylistDialog/index.ts | 17 + .../PersonalListPicker.test.tsx | 286 ++++++++++ .../PersonalListPicker/PersonalListPicker.tsx | 293 ++++++++++ .../components/PersonalListPicker/index.ts | 17 + .../PlaylistCard/PlaylistCard.test.tsx | 57 ++ .../components/PlaylistCard/PlaylistCard.tsx | 131 +++++ .../src/components/PlaylistCard/index.ts | 17 + .../PlaylistEditDialog.test.tsx | 86 +++ .../PlaylistEditDialog/PlaylistEditDialog.tsx | 217 ++++++++ .../components/PlaylistEditDialog/index.ts | 17 + .../PlaylistIndexPage.test.tsx | 52 ++ .../PlaylistIndexPage/PlaylistIndexPage.tsx | 56 ++ .../src/components/PlaylistIndexPage/index.ts | 16 + .../PlaylistList/PlaylistList.test.tsx | 86 +++ .../components/PlaylistList/PlaylistList.tsx | 58 ++ .../src/components/PlaylistList/index.ts | 17 + .../PlaylistOwnerPicker.test.tsx | 215 ++++++++ .../PlaylistOwnerPicker.tsx | 134 +++++ .../components/PlaylistOwnerPicker/index.ts | 17 + .../PlaylistPage/AddEntitiesDrawer.test.tsx | 159 ++++++ .../PlaylistPage/AddEntitiesDrawer.tsx | 239 ++++++++ .../PlaylistEntitiesTable.test.tsx | 211 ++++++++ .../PlaylistPage/PlaylistEntitiesTable.tsx | 218 ++++++++ .../PlaylistPage/PlaylistHeader.test.tsx | 242 +++++++++ .../PlaylistPage/PlaylistHeader.tsx | 197 +++++++ .../PlaylistPage/PlaylistPage.test.tsx | 141 +++++ .../components/PlaylistPage/PlaylistPage.tsx | 133 +++++ .../src/components/PlaylistPage/index.ts | 17 + .../PlaylistSearchBar.test.tsx | 52 ++ .../PlaylistSearchBar/PlaylistSearchBar.tsx | 102 ++++ .../src/components/PlaylistSearchBar/index.ts | 17 + .../PlaylistSortPicker.test.tsx | 68 +++ .../PlaylistSortPicker/PlaylistSortPicker.tsx | 115 ++++ .../components/PlaylistSortPicker/index.ts | 17 + .../src/components/Router/Router.test.tsx | 51 ++ .../playlist/src/components/Router/Router.tsx | 29 + .../playlist/src/components/Router/index.ts | 17 + plugins/playlist/src/components/index.ts | 27 + plugins/playlist/src/hooks/index.ts | 17 + .../src/hooks/usePlaylistList.test.tsx | 225 ++++++++ .../playlist/src/hooks/usePlaylistList.tsx | 284 ++++++++++ plugins/playlist/src/index.ts | 28 + plugins/playlist/src/plugin.test.ts | 22 + plugins/playlist/src/plugin.ts | 74 +++ plugins/playlist/src/routes.ts | 26 + plugins/playlist/src/setupTests.ts | 17 + .../testUtils/MockPlaylistListProvider.tsx | 102 ++++ plugins/playlist/src/testUtils/index.ts | 17 + plugins/playlist/src/types.ts | 27 + .../SearchFilter.Autocomplete.tsx | 3 +- .../SearchFilter/SearchFilter.test.tsx | 16 +- .../components/SearchFilter/SearchFilter.tsx | 6 +- 115 files changed, 9042 insertions(+), 28 deletions(-) create mode 100644 .changeset/calm-snakes-tap.md create mode 100644 .changeset/nice-ducks-smile.md create mode 100644 .changeset/purple-chicken-kneel.md create mode 100644 microsite/data/plugins/playlist.yaml create mode 100644 microsite/static/img/playlist-logo.png create mode 100644 packages/backend/src/plugins/playlist.ts create mode 100644 plugins/playlist-backend/.eslintrc.js create mode 100644 plugins/playlist-backend/README.md create mode 100644 plugins/playlist-backend/api-report.md create mode 100644 plugins/playlist-backend/migrations/20220701011329_init.js create mode 100644 plugins/playlist-backend/package.json create mode 100644 plugins/playlist-backend/src/index.ts create mode 100644 plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.test.ts create mode 100644 plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.ts create mode 100644 plugins/playlist-backend/src/permissions/conditions.ts create mode 100644 plugins/playlist-backend/src/permissions/index.ts create mode 100644 plugins/playlist-backend/src/permissions/rules.ts create mode 100644 plugins/playlist-backend/src/run.ts create mode 100644 plugins/playlist-backend/src/service/DatabaseHandler.test.ts create mode 100644 plugins/playlist-backend/src/service/DatabaseHandler.ts create mode 100644 plugins/playlist-backend/src/service/ListPlaylistsFilter.test.ts create mode 100644 plugins/playlist-backend/src/service/ListPlaylistsFilter.ts create mode 100644 plugins/playlist-backend/src/service/index.ts create mode 100644 plugins/playlist-backend/src/service/router.test.ts create mode 100644 plugins/playlist-backend/src/service/router.ts create mode 100644 plugins/playlist-backend/src/service/standaloneServer.ts create mode 100644 plugins/playlist-backend/src/setupTests.ts create mode 100644 plugins/playlist-common/.eslintrc.js create mode 100644 plugins/playlist-common/README.md create mode 100644 plugins/playlist-common/api-report.md create mode 100644 plugins/playlist-common/package.json create mode 100644 plugins/playlist-common/src/index.ts create mode 100644 plugins/playlist-common/src/permissions.ts create mode 100644 plugins/playlist-common/src/setupTests.ts create mode 100644 plugins/playlist-common/src/types.ts create mode 100644 plugins/playlist/.eslintrc.js create mode 100644 plugins/playlist/README.md create mode 100644 plugins/playlist/api-report.md rename packages/core-components/src/layout/HeaderActionMenu/VerticalMenuIcon.tsx => plugins/playlist/dev/index.tsx (58%) create mode 100644 plugins/playlist/package.json create mode 100644 plugins/playlist/src/api/PlaylistApi.ts create mode 100644 plugins/playlist/src/api/PlaylistClient.test.ts create mode 100644 plugins/playlist/src/api/PlaylistClient.ts create mode 100644 plugins/playlist/src/api/index.ts create mode 100644 plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx create mode 100644 plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.tsx create mode 100644 plugins/playlist/src/components/CreatePlaylistButton/index.ts create mode 100644 plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx create mode 100644 plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.tsx create mode 100644 plugins/playlist/src/components/EntityPlaylistDialog/index.ts create mode 100644 plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.test.tsx create mode 100644 plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx create mode 100644 plugins/playlist/src/components/PersonalListPicker/index.ts create mode 100644 plugins/playlist/src/components/PlaylistCard/PlaylistCard.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx create mode 100644 plugins/playlist/src/components/PlaylistCard/index.ts create mode 100644 plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.tsx create mode 100644 plugins/playlist/src/components/PlaylistEditDialog/index.ts create mode 100644 plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.tsx create mode 100644 plugins/playlist/src/components/PlaylistIndexPage/index.ts create mode 100644 plugins/playlist/src/components/PlaylistList/PlaylistList.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistList/PlaylistList.tsx create mode 100644 plugins/playlist/src/components/PlaylistList/index.ts create mode 100644 plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.tsx create mode 100644 plugins/playlist/src/components/PlaylistOwnerPicker/index.ts create mode 100644 plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistHeader.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/PlaylistPage.tsx create mode 100644 plugins/playlist/src/components/PlaylistPage/index.ts create mode 100644 plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.tsx create mode 100644 plugins/playlist/src/components/PlaylistSearchBar/index.ts create mode 100644 plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx create mode 100644 plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.tsx create mode 100644 plugins/playlist/src/components/PlaylistSortPicker/index.ts create mode 100644 plugins/playlist/src/components/Router/Router.test.tsx create mode 100644 plugins/playlist/src/components/Router/Router.tsx create mode 100644 plugins/playlist/src/components/Router/index.ts create mode 100644 plugins/playlist/src/components/index.ts create mode 100644 plugins/playlist/src/hooks/index.ts create mode 100644 plugins/playlist/src/hooks/usePlaylistList.test.tsx create mode 100644 plugins/playlist/src/hooks/usePlaylistList.tsx create mode 100644 plugins/playlist/src/index.ts create mode 100644 plugins/playlist/src/plugin.test.ts create mode 100644 plugins/playlist/src/plugin.ts create mode 100644 plugins/playlist/src/routes.ts create mode 100644 plugins/playlist/src/setupTests.ts create mode 100644 plugins/playlist/src/testUtils/MockPlaylistListProvider.tsx create mode 100644 plugins/playlist/src/testUtils/index.ts create mode 100644 plugins/playlist/src/types.ts diff --git a/.changeset/calm-snakes-tap.md b/.changeset/calm-snakes-tap.md new file mode 100644 index 0000000000..6b853da53d --- /dev/null +++ b/.changeset/calm-snakes-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Export `HeaderActionMenu` and expose default `Table` icons via `Table.tableIcons` diff --git a/.changeset/nice-ducks-smile.md b/.changeset/nice-ducks-smile.md new file mode 100644 index 0000000000..14153c6350 --- /dev/null +++ b/.changeset/nice-ducks-smile.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-playlist': minor +'@backstage/plugin-playlist-backend': minor +'@backstage/plugin-playlist-common': minor +--- + +Implement playlist plugin, check out the `README.md` for more details! diff --git a/.changeset/purple-chicken-kneel.md b/.changeset/purple-chicken-kneel.md new file mode 100644 index 0000000000..d6a81c7f17 --- /dev/null +++ b/.changeset/purple-chicken-kneel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +Reset page cursor on search filter change diff --git a/app-config.yaml b/app-config.yaml index 7c93d9cbd2..22ca1fcaff 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -444,3 +444,6 @@ apacheAirflow: gocd: baseUrl: https://your.gocd.instance.com + +permission: + enabled: true diff --git a/microsite/data/plugins/playlist.yaml b/microsite/data/plugins/playlist.yaml new file mode 100644 index 0000000000..3d69103d69 --- /dev/null +++ b/microsite/data/plugins/playlist.yaml @@ -0,0 +1,9 @@ +--- +title: Playlist +author: Phil Kuang +authorUrl: https://github.com/kuangp +category: Discovery +description: Create, share, and follow custom collections of entities available in the Backstage catalog. +documentation: https://github.com/backstage/backstage/tree/master/plugins/playlist +iconUrl: img/playlist-logo.png +npmPackageName: '@backstage/plugin-playlist' diff --git a/microsite/static/img/playlist-logo.png b/microsite/static/img/playlist-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5c8d9940175d6221c1bf1cdf9ab473e5793a5fb GIT binary patch literal 14734 zcmd_RWmH_zwkAq|1PBhn2`<6i-QBHlcc*X(?(PnO;O-LK-Jx)I3ob!l<(zZRmDfG` ze|L?ly=SfcO<8lvUN*xO#KfIyUz6jcV_&%nQ3*iYbVNbqA1`1S#)EFlb0 zHHm)={$pVZkTR2#gP;b}un^E6K0!eJg+M@pFKGXwKY;0P|Ct_Y2?6~N3s`{~&asDIPDe}UHo^)X<$gQY6K86YRiZESB#Z)jp~WJ>RD>+lxVpD~pQ%iyi!rkHo^+*@2sZ!OhK$-i?Lc-pQPSiHnPifsvVknVAlZpaXi?IUBmu z*#SxaDda!oh?)Y8oh%)kE$!`y{>n8pvUhRjBO&>#=-;1z+Uaa*_Me*Ufd9%CID-s- zpD-}dGcx?I*ua@pwlueJ2L9X1|HkWX=cxg3()j$(m%3kV`9bt z*6>g5|8UPgt>*n}6Ss)Ht%H*(5D3m4KNIgi?EG(O|C!5w;+0K-_BJkmouOuD>CDgk zFP8t2{6D!AoGeYj-u=t=Z!P~d?SJAGE$p4`!6ofvX)I;uZ0ZCy@n78kq40l?_%E{l z?O1LNQzI3y1XEkE8T@~%0`OmT!Pw9a=xlFn?eJG4{okUpu{1Wd1DY~$F|ji-ae?ax z?_c-*vw;4)od2TfueZ5n|G{bRq^2zUf6!s;0<<)ybFeY=u(1R>)47@&JKHaaZ>H~)MGoLE-ofJ#sc%Wev3S|0F#^JA<$2S+d>^=2;^+M|8vR`dh zww$dlQ+$2g?;G!$*3}*ND=~7J?E86QsEW{0g58!uNz?@-KVSi{-wYdxzd?Q?{t?7h zQm3jaCJ0wYdD7i478d4fy3l-rf1O_6O(PF5fD)w68DMBL%3&L3|nwFMC z_@Sw<`jHr*fPsP3GGc1bNi{2dl(;M^Iz@^c0S$;4pP2I!-aVR52FM>gx90 zqtfxikKTRJG`cyl8_vUTEt;Y*k$-qMBhg$toBcFBzjJt`QD`FHiO1_JMn*5bKw079 z)}EG9);yGk*8U=a@#T*+8H5WRgCVd|;#EjEl+=0Skx7{PZJS(EANk(i(Kfa}*jdHT ziCNhbD)69&u)t25>|!v1b7=gYZod25_Z98rD^-Qwe8AfV|KqD3JdIMF`ny|>mG)Oq zdUI0xI?R+g^YF)B&i51RX_ZEl>hsfqQ<$eqVRQU9MEk+EuInzxlDdy=UNB0UI86;@ zl4nKfXWM38>E;hqW^ccxm(qv4H#U`Ub?HT78QH8Ru3b3O9EkQ2dI+rqdvOL&`K0zz zvqECMk5{oP?0RKjR^we-q(G3)Mrc!u`9ay$Yyx9b*$U=y3h^yegmspL*Ow%Tu0%K! zJ?Ec)HVTCIM2NMVMQ#e)oiB6FFCce~1+wBhJigw5J`@IJ?}zYQ*ymzB#6!t958(zP z{P_br>rng6|$}6hmzq4td1qJhVsHKZKZ}b)gWjCt{v?0q|V|!4B+GeTN z$I#Zbet~@B75cm-pd4LYUaM&3M{T})5MDDP>>HT>%p8)?vA+PsqFa7t< zn*;luL;W@!9)0gG#q?H!`m~moM&_Ux9#=p{rhjxO-&o-us|)@jpqHCmIK(75q`~Le z6#)@3xh$3Gfy!_wsAvxvZIQ+>@b2!eq_mW4o1vX{U4Bvr_roWd$7{zkkLwR>iSj$W zr*^`Ik@E3&1RYU8LnHV<#|>VKj)znxYd9UlwX+S(pN#RBa^GI&Ic zo-~Vvis7v>>AK4mc*Bab?AmuTPOofyk(e|fVA{M;Y|46J-jCZ_UJ0uuhVpCydg#JY z=fq>Fk2)8txH15b-G{q7!+{8lme>1L;)5%b2sBq_iy0I0_!oS6uERB;!*(#1e0WXD zZhwz% z_R6C0v1(_=gHO5-v7&-c70h?GyMxhyHdi{M+NEKrqDQ%L+fww$|df)R)29v{=wDEFFW z^2A^ZL&r+6LOR;k1iFSUQSO?2QpOdASeoQd=z31gtO+S{lyf0R3x{6qMXke(G(ulg?Cb^ferCeM#l2iI zj@<@n+YhK|=$fLcAE=F*B{sFxMZ6Qljt>kSZ+?W{+h1B)iO96?Tz0ybgP|wor1*el zc_L!9QN!V<;v@8OywSFOv$!4b;Da#bhCp%-zr9dJoaNFZwsiTM&i(G8OL%xn391uf z$63!br1${Cgs(!oSmYL`tq5Eyz2PIPYim*V-)}M>C*3-Y(^XwlAc@c2MUcx3DHjK! z7bVF83>YmuA}HPN_hOMkdnLuuh80&wdB1Xq;AntUcS`kNu;n5#f9_YvEn&!A!VtbS zR3rMn^>m5z1XADgK9hxdVb<7w`Avn(HrBGwYrBVv{z;lU6S4T>?ZB1P+E>2LWt96VSkUhD$k7l@Kmo`Ps-C@z~ z?W6C5eX((THQIV90$LV!P4rB}#p7P|I+?d>E=Wes%WDMc7*@{t&MWmzQ`^kDQk111I84TWt;q7=* z8J+7=NH8Ad4$GAGy$YR=mO=IMs#i>e4z%GYF-V%nLlW<8FN!NzGz)W5xj zyPJ}-$f{($tM3m`th_L~o}Lgbsd8Vxzc z)K=rw<{P+D{mWchdJ%o5#)}Wirl?_IEyd=3t<%e+I2g$RF+RE4_9VK!!lVShN+LP+ z3cBzi4Q6rPoTnNO;BAC`&Grc!Oq47{{|MZ`J!8UCAg@@yuUME8^*@)LE`(?lqdH6w?1)tBn+-@B5`9!m0nzJ zmm3ua;!1>f1TijRzumgA00Q3eWxn+L^O8Fgl*s#^sm3kYInwRh9U6vMjTMx#%yUfS z9R_oeXrNo%tk7#7@+}e(NT;l(7$J-*3p|4N?dBTV&7s?pD5`rH2MZKV+quFLO&46( z+gswkFJ+jPg~-+t7T96gXrOLsmG}?2L)O6z6e>y;+Kt%R416Jcv74d6&dg#z9S?0CP1`qo{I%o^bw&aqVE1dIAkM>@K;p7MQ zBXsbwJThn$>9%XO(aTjf2s>{)zOZiIDA5R+w+_E_tshWM6u6<}tf%@FeF;yzS;K)& zKIeUtg-r!hM$nL4WB&bQ3gaqgq9Udry^pa8+MWew&URV(Vg@K%yQa2>P7n`C(V|H( z@Qmia?4|(mi#b@+0BjYg(JH~bxF47t)1O#R58bU%vif4oKD{;bzcLE*c`2a|lb*X8 z_zhKf^--8<-D>6~>(RsS6he(kQvq+q#=gg*HJz19exwcerhlqsw^-`G8BSC*d(gUERp4262Gfx< z4fsGIVsNexhU!3XNXFip>yni4zCzI>H6L9wtBqE|KjsAF>Ntd66VR1>1U zrh}y&W>G9a_eT5Oj*H@SM;2eRFR;LcWmo_k_D6j^x~=UwXgW5|J#6llI<-Qus*HdM z>8v3AOs>k(h$*GUH7z6jN9H$R>o%Q9a;3qFQ&KXED;d@o%De7?DM<~OvZVo+_~8V9 zlA0el%Lc)X^AaJi02O$`k#Ul_!?P?ov@d#gh@-NqGBUPP{>fSW$|eML9o4rul;1DH zMh^Q@Q}b}N6+RoL*FzAPMj4hTngB!`gx&0F#d9N8h zqHFSt%v5HE;|wXZC5)8?;NbbyN0r;Zh>~ce~dg(sYd}(IK5y@)PCzLqRosNzU(3sM-g&d8h1YbxRc&P3? zKLygzCXl&F+zJOIp~`8};2B3)Uz)T!`3Ybfg?vuPwUt22%UDWeOQ~t%0xc{AGx+`) zbANx{w7;_q9-eJ(Y!ogXUGPbi5QL=}%kzG_$sGzr<_}9rNg2^MVK$dE2x1%L21ylq z<#{Bq3^IyZLd}Yk@kJT8K+$g2FC)xN4C4tp@uq7;kyi+=&&>EYcbwaTn7?}6pVdlg z*;Fmt>)wQwAj8cNTgzo;zH=f}VLqezV$WRE%Y{u*BxA(E=Jo&XsV zHXS)Uvy$?IU-7hf#LFL381(H>)j(eHZxwQYi41q6)m((=un@l8D3%!O#%^>PxoxX_ z&dScp!stkrSC&WpItnKW+h5by=;4KV+I2>mO`lVXMe2_KzB3!M<&k+W zA?(_(#BDgOp`NLN$##q|%cZ=H@S@xC%gf7aT~5`**jUafu0#h2*|RI9j-6FoD{D2; zSOI+lwUGF!(LI#U%j~lWLh(g4B4IWqt0REkh)>C;$g8WXjw9r$TPNk!ITjeFjzj)_ z00uOn+d#sXZj#@QIz|b_igZZU@?5n5!Wf;^y~bycCBZ(^ATF*4;RUrwJvf?@av&!FeFE&LOanp(8u zAcX5Mm9cgsGQ)jD>P%K#;!4&6^bWmJ4>hh1H26W`m7boSK7ys=4&&qU!|Z%(a$2Q2 zr8wt4iW)MU)bL|I*+f9stw~TBHP<^^2m)Q8!E|U~Y*!eB20AP|h$NfCYc!F06(608YdYH`xSzoj!NRFClu_V0vib zE<;`bKK+-O)hg?d{*48ZkXy$kZ%2O?%jrQFZFVw6*H$$78ColRx<`|dRbI%b-R3sTtg=`XM;8X ziF>fcW+(uckf7uB&_Y}Q5+NT&WohirXh6=?is?bkn0kl$0ZtG+ydP&Irm$m=)wplo zUK^_p30z@IaOxfNsFjoL1$EwWoq7K@Wc`FwH|nSrYGHctof>JF^F#0W5qVM#%jf0| zn_gJJiW=+LOeSaM8h)%x4a+J{q~Y?iefO_s{Se)7+D~;-Aw*5a=^O#(7p+i#9w9_f zOI2`Ww`&q&So#6<1{O-axLS@kx;Bq>Y z&f@w8gwmtY@w)k%eX(SuHazLss73}&`M%1VH(#Tj)=cWy^FDc-1`FoAF7nn#@1@}m zqu&Ch3loj2a8#N0YW)4*d>@z3FB$Dx5?Fv)XkaTetD}oiNNR^mf z0Yj1vYDefH-QCkfWt@{MzfN7e-{Et6r0hLuesNiszita`%^z@E>B=LG9B?Mf8|8Rt zBdv@EeMrBwtC<=Z-+D(^KlRLG7Wea6B$4AJfy=}Y85heQX-^rYmd`%zW7&MB-wg@0 z*b_w&P^*?zuc=dFtfVTHuDhNiImI?^GmR3hwJ0-;oSE*L5cCtJ|0Y+3D#OezwKj)) zl75w|M~Sp88K0NcF3QFP$X7g@+O7`y4qgPTnB`DF}Aw{e79qnlB=@3W?Duk;{X zI&-7j#YU?#rRg7hW-RqOPt~x8))nxY2PntRtnCjYQD;dtKLRE_%nLH{axMEa@Gd zT8El97x(F5c|LkqwMHOKn(PUWKD93cqc2hKM5l# zY|Szuh9nayN6xieQjJQ8BEt{ZaePSd!d;)%g|jefn#~*?d*C0pnYbA^4C@RAGaEwJ zvX-To;!-_{sa$&KK@M$r>;4#t6{7&8F$=F4MDlXpfp+pUXEv4&I~-C2MkQO-AuqAz zp`&8(s&^6`STb`dEQSbb8Z4w0ngTRApIHhDwoGo)QSM|y5R1=hElRp2*X{QRKN7|d z(5ij%5M+ENO(-UvYz6?93W6!Hdj^GiIJXxK#K`Yh%#J(la&0}O?PIhDa)BD^W!d) z2o#mZOyvHzarkios|TIUyrAqpHd?I-ki$>HIjP<-^(12*dJb>Bgz=sRp7Es3DHAi@ zuRad$KEqBkrGxv$2FJ6>4w4CW^o$q|UfXUhD1`XJ_7@OFBB*C8tx)0qA6kHp^C5L5 z)m46rSUYub{A5N-3CU%FM(f z2K@AZ!3m1#6+$tFmKE)F;VjREeL%x+)*xKW9u>{NFR7UcYFmOg%Ofvc1XUk3de*w+ zs(!FdIPytx&98@i)z0bb#Ci`4thN;*#VWD7#C~%D-rK>M5@vnSF%A7Waq+Lh;lsA57+4;1)jI98)R5Zp<2^YGb2@+fI88k+5_{26Iy{)VBy2!1p0 zDREM;ojHg-qrc4o*j=GN=Y{8yu6FNdIng962qk2X)XUy`#N5#)Y=|lMjTR^RD9u#hbYkn-UWhv^ctDIDMuFDsyKRQ)6T24bR@_d9y?@VS+Dydd>L%Qls{n(Kh|GMV_$;naz*(v?Y zS9y~Zlw7jJRCt_EFwdp0IyzjVg>tKd1Ttt+lx1aBimQr|g1UV2{O=PbRsaN6IuY{~ z|G*jAk)u8$0b~;$3(jXFowYj5hmEJHrM7pMs+iyVk?JY)KMoFMgd^G&3sx&V7Xp6n z{dIGW__*Q7RbBO;bLDK1Cw5&(+^7 zu3(Qw=R$MUli3-f?|X`Q=Ig?;Grwl%neQ_{UE9Z%Ur?_6eLXqd4%v8ps@8I@$nd9S zg~%wdD=jub()(&>pygr1Yq>gs!v(}lX`AT8J3?tK9NP&}9bcGPOt?s>Qyb;kxI#Kx zZAOO2q)jstXqr9(_KUUG87A0zT@WFGD!V1#j`6}iX4X_&hs|H+M`SdnZ>;^gg=kuT z0P+Gib+@`{sRQ)pgZp5A;isg_W-cX+crMpgQ$;E+_n=CBCzLLnL6T8DO}&h?gt}N)D)$lvehmNkA&BKgGHqY!6-K6^3Xmf*s9)NQrYz=C{-oR^$(24nvyar?+ zb{hbIBZ}T=Zt{%zawhQ}u{U|>aJ|D#HWxrDcO*M|jU-c@@nV9C+~j>tSgWtuzlSuN zgXpeX;`SUDg4{;XinXfe{mIvHVsp0vp1#*V23yBp+IavcY5QjPd{HkJi+ktD?47NF zD9YUk1<5nsbT_{`_!mBV3=l1RK-o?`o_rqR-I&&J06(RWdI z@>O9jB{L-Xt>ueH&Xpc3x-DV8esG1J)d2L6f;Nl1_a%$I;13USS62jLGQCZ21Q}f_ zeD4=j-rGKVLqnp_UoPdSIA?{WC#KUPc^sDL18=nCfiDycOg)=@dHE`-)j}{D;=b1) z29l;5)2y4kt|8)4!DnnfA5{Db+io6#J2BA?w)p~KaV-h_=44+@AimQMg?-XC^G3(H z@j+kl-=%amcJ`gO=Zm4(@3*8nK6eYD6NZjk_~o){BJ#P*MP z-+4YlWxFY3otTdzciN!&*rjqdiiD*8~hSZDgyuuJmNeXv$Okvx{i`eMT2$is)s z;2s9k;BwOLiICwQqM%!j<}ycFjytq#;O|f7=QWpt77HL~cLTxeB?i>EstMY@cjfv6 zw$1CV*k+cT_pa`TB?3h&5JjGE-yADUj*Je*WF+-CReXrUQe2f+5v6ly_5I=BPoUgA zhynpI#vM`U{B4CFwBI(f-5-ZG2XP{;E&7W}mZ{X3qZzZMJq)KD(ueC;3ix-{53uQX z!*0B5n^@Tm9(Es$fSi87_XD%`d0dfc6){BWe%TqwgUEp82qzGBMJ}j4)gI0=L&Aj9 z##fse%lyf zbr^V_Zu9j^zacUOVHXkbw=8%JkElfrvfEN-aV1Sv@WLw}ERt?1&C#b#)se|Ey+%uz z_#U%kOmWi;eHV&-$kTtN`0$Gbh4%)seGOC0kHuc63Odw$_Hp9t<{-5%E@E<{B-t#2 zk%0?yQF!8W*zp<8=7`H&IW(LpC)p;iQ~H%LLt`mV~Ahd57Z$*Byc^lNGq zq$c0SQ0v{O0r(FrNyp)X=<2MA7y}}Hw)rc7$OByK`dF$^g?R0!%BFMywe%%T!3P7h z?LkahoeqL*d~T^(ZG6Emjq7c-`@i4215R+sj-s6ATFG1;Hl*?$Xi&tCtj}|5zL7d$ z0zn(JDvPEQc`h|wzZ&vT+j6`Jpm<#KQ!?24P^3KUJVu7i(r1N1`4gS$SDkS1>_bSb zDK)@9l{5@Q#NAgZw1MQGu;R%UuVe`0G`|MUBf=5M*CIn&pPWh4x)1&x8GFM%EHu(sebfvQ0cS%endAbim^IVpKDqdf3W@EwX?U!J`)DY~JXf&FTA&OE?HK+sK3|UZZO1$2Rm<8~ zAqzTHZZF<(B|vA6baOt}!K~^>P&Q7M`7OO>0@Om|Js^AcEm)}X#xY(7DraANXetKmuGS=Qj8 zERZNiQ!2P6VX6nC1N|}Y@@y?%Qq{{O=&o7&;kqBc7daezLMEd5VciB_zC_& z19RFZ$&d{Zm@VTLgV7Pqp0Hv{81C|?T)7xtftWZzR*05af zD~I|(DvHp-HC`<^9<0;kR{{H)fQ&Kw^iBfDPP5&k3+uo|g=X4`-DP?L2IH)sB9cIY z3bs!)MRlfliZ@d=_qn#T6hL2N(rk*GxH-qOnT>_xma!{cmEO-CS%OHDz`J_=qhhzE z9t1Rc4)oI2qf*l-$Cc4yGN{~Ok`)gMnVg3)r<|(u*W^6%m2reOb4D?xcP$6{Tl3gq zt+*Qi#p_vDQW4Zt>mSuQ|0Ki3D2g3cFH1dTYyX%c-sdR07%ww2HBp=|Jd*tbFA5&% z0Ez2}DXAj4Um^Mg#)*vx1O_RhioKI)mvbK4;p8zAo~5OdT1Dt72(p(BXUQ=oHd*}> zk|=%7(u{A7m0raxm$S?LTo;lm<;>23^?=dGFU%cukz~&mI0p(&Ei@IfZ}Nj*ro;zU*I^yq$+^4}%@OK3N0cqix(k9c%_4F+ zpBoXfYx48Yb`K3OzCMsnh3eqFU+YOikTwG+m*&XIND>%JPcDwpk=M6Y{)BRFw^(oLKXnh};RA-eI zgUE|*w|JMKZ{%AQh5kIPYR$~GVhJ6ji<9o+7p22u;=@NEF>GUru*gGxJi!V?cy{591Sn{~fdID<|5F{U23p#TI4C#KSplQLS?EBR z6{EV(?|Z6AssTte-1_&)$zb6{X9nD`h$IZ~vcS0H!Q}Fi6nR#Oq9+_J)wD}=(DTjs zl^^6`cEOQSBP?z?4}*l?eYdC|i|lhGlG0Q|86X2iZ`Z%CCzp^aT_^DU^;ExEk|v!p zrg>QO^67;7Y&)_7xXR92-36gb#j)b~NpZCS-~4_5`SLpZJ)|C!gGescDFUuLn;^&e z@s&a~o13^|8*eOYKL~1a`ihD0%KF*Wct8Enc=_0TdwG&orN+rcrfN6QYBSiMPrEkY zSb>GCrXC@`HU{hcn0E@$D@|Yg`uq?`gSDlS`;=5@DkhUI4H$WO5AS-02Jdc!KmTr< z(wfHkpG@O>ro{j;sYTBJpL=*ohEoOEn! zGJG1rzF~e8s7jqZ3=US+J1hHoz)*~poGETHe+;izU+)UlnTb?91~b8gM6a%fVD;h= z&U+n3v9%~z27vjS|Lwf!O&I6>Y5z|-cr1L56FE@hdaebpscAgK9=^}fCZLg1Lr9lQ zd(h~(D_)`BwV~y?cSK528!AFvYJvoBeNwx>aOmi8BLbW2M36eYh06g4ldas?@>u;2 z^R`RFVW8QV*_!eq87FJhJId+^GnKl`jMl=~*em-+R-S|p?mbp~QGD;?Pq(!@kzjtc zW|8-irn0ILFLz>1tv~Qol)wWq9{5`<@{x1d8&{`#>Z5hFB_x-@Tbc(4X1tGEf$Ea0 zCMU&fPtDi7`KAmVx5_eOpvA>lcl<`e|7OC`_~ zIlXT4qMVIdas!RiG0rl@Lw;TD*uS9{>v&__D+Zf&Brk0&#@^Yt;^+17^FG!44vmbZ zYSo+8olQvtwp1_UQzcTA)HMfb2e{C;8$n34#W-)E*f&1cf_C*;2TIZ!EvsJ6+aZ{m z_fnXetkW0iI<|Ca4wngj+}PHebpRrbkJ>8f8u;we+uNJe!l)|lUV$BJPvHJXvKUIu zI*}~PpZheRABFT>*KQekWaT=fQ%sXzO5H7pqG{|NKkry`Y$yNbgq$x?dqcon+^c=f zYrDEd?urhMVzja;sXzEpbj-)U0U>@O5fnh*0Hk#{*M}VA=s?GMTQ{$Do9=P(G65|3 zuMnkHjXUpRap*^80I;aj7e`2y6ueze%-=N97Oe%!t(G9s#L?8L)rP5aR2iV4_Ux&4 zoHHzNB&1NDI9bL8wMQpf|7){!yN^&G_YgS(Q-sg zTKj3eC`f%@3kYRZTot^qNH&Njy%wKqudb1I|Gcq2CE9rgiRf%20ltiGHQ@=wJpKO4 zS;`*d4`^ph5(DxJ*nGx9MqPg3A(?o28I$atoGQb8FO7twkvQNSq#h7DjPKv|To$lB zB^0FA3G8~!-Ry(^^XUwG&jH@p-RBRqmK9V9aPYEwsw))hq62=SRH#AKfsk+Fn)!;+ zmnoSZtrtIL``57Y2=!<}lwd4O$LW5Li~fzU}On?ah= z@aJZv$|+>aJ5Tdg_kqAxL6PSqQ3OE5;b(4-C&a5cG)gkTK)Y+KOR%qC*R<<86 z+s>k=&F&BXuRi#zr#Av<>yxxb#=eo?a9PSzYLF`rTgz?VBlxEHqDAcqg`Ek4kEL80 z>A5ZnVRC|!{V>YA#$JZb=t+ecfN?V4t9XHYpsWY>AoUK^z)qt3Tk%pRE{CK&c)yH> z^s%6q-Y;(#0NkpII6E&ib6~fz(IFCBfE@fMF;A=XI2?+B393!g}<~RI!$p@xsh94xQZ{TzX6X4LAPg3k6%VaPr)QMz5b6K4dvsa$X(F|ir z40`mB&;~Mn{UyHe_^UW zG*;@JjMpNpt{o$dnQpOp-C1aa#9ns8n0VB3!yTJ!gDuwe#=+I7+`S+`5KRQBa;EE& z;sn+UQ*)=2DdD#CW@Y+l5!N%-Mal>y-Nx6$PM4}mT^D&h)&6t-LpCro@8a)eTzZ*#Ac$@So5(s z=RuuT#|yVCwNfxdMh&T;Rh~PwGD$4$n37~0JFN#*4>?;>DCWNkHN>CcR)od4AaP-VXi)(nTMM+%p>5^$z#|72#=dm8A78fBcO~(nHGvFhcNqr zElkoEYc{ID%InT_&x;%N00re$1{Ma}O6o9qY=ECBkRwZnkvnJ0Nu!~-BMM_udEoHK zf?FM2_M(z(XOg^8udcMc1g{3{niklJ18A6lqxFdU!cThz52}+RY$nSRrUFgoaeXYT zk>^Lny|Val8F5Le7e1D zzMtXR(>3=j`1}<|vBJI`7DHK&b4!37F8{X*{{Hw+x%|?D){MtthH&2+F@W_@D!kYc$mLAg;{2iqn8oe1>z`1YDD3eGx zN#T1b_Y_@&%!cHbLc@AQC#;`~Qj4O0ilKh<7mO*YO6=nl1_h|orq$o)4S;O?OUjsR zZHjJG;CQl+aJ_A@>Mvw!8xPzuD+>LO@4i-l%N`Oj-|3<Nc;=c*GFe0GHQN4zCk z=D7u8qH^wdq=^yVg8pvtG5y`*Ln!{^r5az{>@A3G&spqUkcA|bR5Ry)LaQ_P+gkn= z)O2j^o6?!jC#&+b2zQokLhEqMfBC|Ka=3}E@PqD{I6|-$9P2{2n4#4A#UBkE)gt4U z-}c4d2^> } /> } /> + } /> ); diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 30da01841c..8b5f0932fb 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -22,6 +22,7 @@ import RuleIcon from '@material-ui/icons/AssignmentTurnedIn'; import MapIcon from '@material-ui/icons/MyLocation'; import LayersIcon from '@material-ui/icons/Layers'; import LibraryBooks from '@material-ui/icons/LibraryBooks'; +import PlaylistPlayIcon from '@material-ui/icons/PlaylistPlay'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import SearchIcon from '@material-ui/icons/Search'; import MenuIcon from '@material-ui/icons/Menu'; @@ -105,6 +106,7 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( /> + {/* End global nav */} diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index e15df4bc6c..c2f297a2d7 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -104,6 +104,7 @@ import { EntityPagerDutyCard, isPagerDutyAvailable, } from '@backstage/plugin-pagerduty'; +import { EntityPlaylistDialog } from '@backstage/plugin-playlist'; import { EntityRollbarContent, isRollbarAvailable, @@ -114,6 +115,7 @@ import { EntityTechInsightsScorecardCard } from '@backstage/plugin-tech-insights import { EntityTodoContent } from '@backstage/plugin-todo'; import { Button, Grid } from '@material-ui/core'; import BadgeIcon from '@material-ui/icons/CallToAction'; +import PlaylistAddIcon from '@material-ui/icons/PlaylistAdd'; import { EntityGithubInsightsContent, @@ -155,6 +157,7 @@ const customEntityFilterKind = ['Component', 'API', 'System']; const EntityLayoutWrapper = (props: { children?: ReactNode }) => { const [badgesDialogOpen, setBadgesDialogOpen] = useState(false); + const [playlistDialogOpen, setPlaylistDialogOpen] = useState(false); const extraMenuItems = useMemo(() => { return [ @@ -163,6 +166,11 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { Icon: BadgeIcon, onClick: () => setBadgesDialogOpen(true), }, + { + title: 'Add to playlist', + Icon: PlaylistAddIcon, + onClick: () => setPlaylistDialogOpen(true), + }, ]; }, []); @@ -180,6 +188,10 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { open={badgesDialogOpen} onClose={() => setBadgesDialogOpen(false)} /> + setPlaylistDialogOpen(false)} + /> ); }; diff --git a/packages/backend/package.json b/packages/backend/package.json index a8ae29ee18..eb0e0d58e5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -46,6 +46,7 @@ "@backstage/plugin-permission-backend": "^0.5.11-next.2", "@backstage/plugin-permission-common": "^0.6.4-next.2", "@backstage/plugin-permission-node": "^0.6.5-next.3", + "@backstage/plugin-playlist-backend": "^0.0.0", "@backstage/plugin-proxy-backend": "^0.2.30-next.2", "@backstage/plugin-rollbar-backend": "^0.1.33-next.3", "@backstage/plugin-scaffolder-backend": "^1.6.0-next.3", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index de3f435508..cb9c9bf580 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -57,6 +57,7 @@ import app from './plugins/app'; import badges from './plugins/badges'; import jenkins from './plugins/jenkins'; import permission from './plugins/permission'; +import playlist from './plugins/playlist'; import { PluginEnvironment } from './types'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -139,6 +140,7 @@ async function main() { createEnv('tech-insights'), ); const permissionEnv = useHotMemoize(module, () => createEnv('permission')); + const playlistEnv = useHotMemoize(module, () => createEnv('playlist')); const apiRouter = Router(); apiRouter.use('/catalog', await catalog(catalogEnv)); @@ -158,6 +160,7 @@ async function main() { apiRouter.use('/badges', await badges(badgesEnv)); apiRouter.use('/jenkins', await jenkins(jenkinsEnv)); apiRouter.use('/permission', await permission(permissionEnv)); + apiRouter.use('/playlist', await playlist(playlistEnv)); apiRouter.use(notFoundHandler()); const service = createServiceBuilder(module) diff --git a/packages/backend/src/plugins/permission.ts b/packages/backend/src/plugins/permission.ts index 0d3dcc588d..7192a1ddec 100644 --- a/packages/backend/src/plugins/permission.ts +++ b/packages/backend/src/plugins/permission.ts @@ -14,17 +14,34 @@ * limitations under the License. */ +import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; import { createRouter } from '@backstage/plugin-permission-backend'; import { AuthorizeResult, PolicyDecision, } from '@backstage/plugin-permission-common'; -import { PermissionPolicy } from '@backstage/plugin-permission-node'; +import { + PermissionPolicy, + PolicyQuery, +} from '@backstage/plugin-permission-node'; +import { + DefaultPlaylistPermissionPolicy, + isPlaylistPermission, +} from '@backstage/plugin-playlist-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; -class AllowAllPermissionPolicy implements PermissionPolicy { - async handle(): Promise { +class ExamplePermissionPolicy implements PermissionPolicy { + private playlistPermissionPolicy = new DefaultPlaylistPermissionPolicy(); + + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { + if (isPlaylistPermission(request.permission)) { + return this.playlistPermissionPolicy.handle(request, user); + } + return { result: AuthorizeResult.ALLOW, }; @@ -38,7 +55,7 @@ export default async function createPlugin( config: env.config, logger: env.logger, discovery: env.discovery, - policy: new AllowAllPermissionPolicy(), + policy: new ExamplePermissionPolicy(), identity: env.identity, }); } diff --git a/packages/backend/src/plugins/playlist.ts b/packages/backend/src/plugins/playlist.ts new file mode 100644 index 0000000000..0d31158842 --- /dev/null +++ b/packages/backend/src/plugins/playlist.ts @@ -0,0 +1,37 @@ +/* + * 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 { IdentityClient } from '@backstage/plugin-auth-node'; +import { createRouter } from '@backstage/plugin-playlist-backend'; +import { Router } from 'express'; +import { PluginEnvironment } from '../types'; + +export default async function createPlugin({ + database, + discovery, + logger, + permissions, +}: PluginEnvironment): Promise { + return await createRouter({ + database, + identity: IdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + }), + logger, + permissions, + }); +} diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 831eaebb66..895581c702 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -24,11 +24,8 @@ import { UrlReader, } from '@backstage/backend-common'; import { PluginTaskScheduler } from '@backstage/backend-tasks'; -import { - PermissionAuthorizer, - PermissionEvaluator, -} from '@backstage/plugin-permission-common'; import { IdentityApi } from '@backstage/plugin-auth-node'; +import { PermissionEvaluator } from '@backstage/plugin-permission-common'; export type PluginEnvironment = { logger: Logger; @@ -38,7 +35,7 @@ export type PluginEnvironment = { reader: UrlReader; discovery: PluginEndpointDiscovery; tokenManager: TokenManager; - permissions: PermissionEvaluator | PermissionAuthorizer; + permissions: PermissionEvaluator; scheduler: PluginTaskScheduler; identity: IdentityApi; }; diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 3dc4e2848e..20e14312bb 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -16,15 +16,18 @@ import { CardHeaderProps } from '@material-ui/core/CardHeader'; import { Column } from '@material-table/core'; import { ComponentClass } from 'react'; import { ComponentProps } from 'react'; +import { ComponentType } from 'react'; import { default as CSS_2 } from 'csstype'; import { CSSProperties } from 'react'; import { ElementType } from 'react'; import { ErrorInfo } from 'react'; import { IconComponent } from '@backstage/core-plugin-api'; +import { Icons } from '@material-table/core'; import { IdentityApi } from '@backstage/core-plugin-api'; import { LinearProgressProps } from '@material-ui/core/LinearProgress'; import { LinkProps as LinkProps_2 } from '@material-ui/core/Link'; import { LinkProps as LinkProps_3 } from 'react-router-dom'; +import { ListItemTextProps } from '@material-ui/core/ListItemText'; import MaterialBreadcrumbs from '@material-ui/core/Breadcrumbs'; import { MaterialTableProps } from '@material-table/core'; import { NavLinkProps } from 'react-router-dom'; @@ -50,6 +53,16 @@ import { Theme } from '@material-ui/core/styles'; import { TooltipProps } from '@material-ui/core/Tooltip'; import { WithStyles } from '@material-ui/core/styles'; +// @public (undocumented) +export type ActionItemProps = { + label?: ListItemTextProps['primary']; + secondaryLabel?: ListItemTextProps['secondary']; + icon?: ReactElement; + disabled?: boolean; + onClick?: (event: React_2.MouseEvent) => void; + WrapperComponent?: ComponentType; +}; + // @public (undocumented) export function AlertDisplay(props: AlertDisplayProps): JSX.Element | null; @@ -432,6 +445,14 @@ export function GroupIcon(props: IconComponentProps): JSX.Element; // @public export function Header(props: PropsWithChildren): JSX.Element; +// @public (undocumented) +export function HeaderActionMenu(props: HeaderActionMenuProps): JSX.Element; + +// @public (undocumented) +export type HeaderActionMenuProps = { + actionItems: ActionItemProps[]; +}; + // @public (undocumented) export type HeaderClassKey = | 'header' @@ -1333,6 +1354,12 @@ export type TabIconClassKey = 'root'; // @public (undocumented) export function Table(props: TableProps): JSX.Element; +// @public (undocumented) +export namespace Table { + var // (undocumented) + tableIcons: Readonly; +} + // Warning: (ae-missing-release-tag) "TableClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 65edb5b69b..b04c247b2f 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -292,6 +292,9 @@ export function TableToolbar(toolbarProps: { ); } +/** + * @public + */ export function Table(props: TableProps) { const { data, @@ -519,3 +522,5 @@ export function Table(props: TableProps) { ); } + +Table.tableIcons = Object.freeze(tableIcons); diff --git a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx index d8dc398ce3..125363fe0a 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx +++ b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx @@ -23,9 +23,12 @@ import ListItemText, { ListItemTextProps, } from '@material-ui/core/ListItemText'; import Popover from '@material-ui/core/Popover'; -import { VerticalMenuIcon } from './VerticalMenuIcon'; +import MoreVert from '@material-ui/icons/MoreVert'; -type ActionItemProps = { +/** + * @public + */ +export type ActionItemProps = { label?: ListItemTextProps['primary']; secondaryLabel?: ListItemTextProps['secondary']; icon?: ReactElement; @@ -61,10 +64,16 @@ const ActionItem = ({ ); }; +/** + * @public + */ export type HeaderActionMenuProps = { actionItems: ActionItemProps[]; }; +/** + * @public + */ export function HeaderActionMenu(props: HeaderActionMenuProps) { const { actionItems } = props; const [open, setOpen] = React.useState(false); @@ -84,7 +93,7 @@ export function HeaderActionMenu(props: HeaderActionMenuProps) { padding: 0, }} > - + { + return await createRouter({ + database, + identity: IdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + }), + logger, + permissions, + }); +} +``` + +With the `playlist.ts` router setup in place, add the router to `packages/backend/src/index.ts`: + +```diff ++import playlist from './plugins/playlist'; + +async function main() { + ... + const createEnv = makeCreateEnv(config); + + const catalogEnv = useHotMemoize(module, () => createEnv('catalog')); ++ const playlistEnv = useHotMemoize(module, () => createEnv('playlist')); + + const apiRouter = Router(); ++ apiRouter.use('/playlist', await playlist(playlistEnv)); + ... + apiRouter.use(notFoundHandler()); + +``` + +## Setting up plugin permissions + +You configure permissions for specific playlist actions by importing the supported set of permissions from the [playlist-common](../playlist-common/README.md) package along with the custom rules/conditions provided here to incorporate into your [permission policy](https://backstage.io/docs/permissions/writing-a-policy). + +This package also exports a `DefaultPlaylistPermissionPolicy` which contains a recommended default permissions policy you can apply as a "sub-policy" in your app: + +```diff +# packages/backend/src/plugins/permission.ts + ++import { DefaultPlaylistPermissionPolicy, isPlaylistPermission } from '@backstage/plugin-playlist-backend'; +... +class BackstagePermissionPolicy implements PermissionPolicy { ++ private playlistPermissionPolicy = new DefaultPlaylistPermissionPolicy(); + + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { ++ if (isPlaylistPermission(request.permission)) { ++ return this.playlistPermissionPolicy.handle(request, user); ++ } + ... + } +} + +export default async function createPlugin(env: PluginEnvironment): Promise { + return await createRouter({ + config: env.config, + logger: env.logger, + discovery: env.discovery, + policy: new BackstagePermissionPolicy(), + ... +``` diff --git a/plugins/playlist-backend/api-report.md b/plugins/playlist-backend/api-report.md new file mode 100644 index 0000000000..5c86b6ae45 --- /dev/null +++ b/plugins/playlist-backend/api-report.md @@ -0,0 +1,93 @@ +## API Report File for "@backstage/plugin-playlist-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; +import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; +import { Conditions } from '@backstage/plugin-permission-node'; +import express from 'express'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { Logger } from 'winston'; +import { Permission } from '@backstage/plugin-permission-common'; +import { PermissionCondition } from '@backstage/plugin-permission-common'; +import { PermissionCriteria } from '@backstage/plugin-permission-common'; +import { PermissionEvaluator } from '@backstage/plugin-permission-common'; +import { PermissionPolicy } from '@backstage/plugin-permission-node'; +import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; +import { PluginDatabaseManager } from '@backstage/backend-common'; +import { PolicyDecision } from '@backstage/plugin-permission-common'; +import { PolicyQuery } from '@backstage/plugin-permission-node'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; + +// @public (undocumented) +export const createPlaylistConditionalDecision: ( + permission: ResourcePermission<'playlist-list'>, + conditions: PermissionCriteria< + PermissionCondition<'playlist-list', unknown[]> + >, +) => ConditionalPolicyDecision; + +// @public (undocumented) +export function createRouter(options: RouterOptions): Promise; + +// @public +export class DefaultPlaylistPermissionPolicy implements PermissionPolicy { + // (undocumented) + handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise; +} + +// @public (undocumented) +export const isPlaylistPermission: (permission: Permission) => boolean; + +// @public (undocumented) +export type ListPlaylistsFilter = + | { + allOf: ListPlaylistsFilter[]; + } + | { + anyOf: ListPlaylistsFilter[]; + } + | { + not: ListPlaylistsFilter; + } + | ListPlaylistsMatchFilter; + +// @public (undocumented) +export type ListPlaylistsMatchFilter = { + key: string; + values: any[]; +}; + +// @public (undocumented) +export const playlistConditions: Conditions<{ + isOwner: PermissionRule< + PlaylistMetadata, + ListPlaylistsFilter, + 'playlist-list', + [userOwnershipRefs: string[]] + >; + isPublic: PermissionRule< + PlaylistMetadata, + ListPlaylistsFilter, + 'playlist-list', + [] + >; +}>; + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + database: PluginDatabaseManager; + // (undocumented) + identity: IdentityClient; + // (undocumented) + logger: Logger; + // (undocumented) + permissions: PermissionEvaluator; +} +``` diff --git a/plugins/playlist-backend/migrations/20220701011329_init.js b/plugins/playlist-backend/migrations/20220701011329_init.js new file mode 100644 index 0000000000..17a71e8438 --- /dev/null +++ b/plugins/playlist-backend/migrations/20220701011329_init.js @@ -0,0 +1,60 @@ +/* + * 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. + */ + +exports.up = async function up(knex) { + await knex.schema.createTable('playlists', table => { + table.comment('Playlists table'); + table.uuid('id').primary().comment('Automatically generated unique ID'); + table.text('name').notNullable().comment('The name of the playlist'); + table.text('description').comment('The description of the playlist'); + table.string('owner').notNullable().comment('The owner entity ref'); + table + .boolean('public') + .defaultTo(false) + .notNullable() + .comment('Whether the playlist is public'); + }); + + await knex.schema.createTable('entities', table => { + table.comment('The table of playlist entities'); + table + .uuid('playlist_id') + .notNullable() + .references('playlists.id') + .onDelete('CASCADE') + .comment('The id of the playlist this entity belongs to'); + table.string('entity_ref').notNullable().comment('A entity ref'); + table.unique(['playlist_id', 'entity_ref']); + }); + + await knex.schema.createTable('followers', table => { + table.comment('The table of playlist followers'); + table + .uuid('playlist_id') + .notNullable() + .references('playlists.id') + .onDelete('CASCADE') + .comment('The id of the playlist being followed'); + table.string('user_ref').notNullable().comment('A user entity ref'); + table.unique(['playlist_id', 'user_ref']); + }); +}; + +exports.down = async function down(knex) { + await knex.schema.dropTable('playlists'); + await knex.schema.dropTable('entities'); + await knex.schema.dropTable('followers'); +}; diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json new file mode 100644 index 0000000000..bbea8163fb --- /dev/null +++ b/plugins/playlist-backend/package.json @@ -0,0 +1,52 @@ +{ + "name": "@backstage/plugin-playlist-backend", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "^0.15.1-next.2", + "@backstage/backend-test-utils": "^0.1.28-next.2", + "@backstage/config": "^1.0.1", + "@backstage/errors": "^1.1.0", + "@backstage/plugin-auth-node": "^0.2.5-next.2", + "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/plugin-permission-node": "^0.6.5-next.2", + "@backstage/plugin-playlist-common": "^0.0.0", + "@types/express": "*", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + "knex": "^2.0.0", + "node-fetch": "^2.6.7", + "uuid": "^8.2.0", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.19.0-next.2", + "@types/supertest": "^2.0.8", + "msw": "^0.47.0", + "supertest": "^6.1.3" + }, + "files": [ + "dist", + "migrations/**/*.{js,d.ts}" + ] +} diff --git a/plugins/playlist-backend/src/index.ts b/plugins/playlist-backend/src/index.ts new file mode 100644 index 0000000000..eeccd8913f --- /dev/null +++ b/plugins/playlist-backend/src/index.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. + */ + +/** + * Playlist backend plugin + * + * @packageDocumentation + */ +export * from './service'; +export { + createPlaylistConditionalDecision, + DefaultPlaylistPermissionPolicy, + isPlaylistPermission, + playlistConditions, +} from './permissions'; diff --git a/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.test.ts b/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.test.ts new file mode 100644 index 0000000000..179b0d7f9b --- /dev/null +++ b/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.test.ts @@ -0,0 +1,135 @@ +/* + * 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 { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; +import { + AuthorizeResult, + createPermission, +} from '@backstage/plugin-permission-common'; +import { + permissions, + PLAYLIST_LIST_RESOURCE_TYPE, +} from '@backstage/plugin-playlist-common'; + +import { playlistConditions } from './conditions'; +import { DefaultPlaylistPermissionPolicy } from './DefaultPlaylistPermissionPolicy'; + +describe('DefaultPlaylistPermissionPolicy', () => { + const policy = new DefaultPlaylistPermissionPolicy(); + const mockUser: BackstageIdentityResponse = { + token: 'token', + identity: { + type: 'user', + ownershipEntityRefs: ['user:default/me', 'group:default/owner'], + userEntityRef: 'user:default/me', + }, + }; + + it('should deny non-playlist permissions', async () => { + const mockPermission = createPermission({ + name: 'test.permission', + attributes: { action: 'read' }, + }); + + expect(await policy.handle({ permission: mockPermission })).toEqual({ + result: AuthorizeResult.DENY, + }); + }); + + it('should allow create permissions', async () => { + expect( + await policy.handle({ permission: permissions.playlistListCreate }), + ).toEqual({ result: AuthorizeResult.ALLOW }); + }); + + it('should return a conditional decision for read permissions', async () => { + expect( + await policy.handle( + { permission: permissions.playlistListRead }, + mockUser, + ), + ).toEqual({ + result: AuthorizeResult.CONDITIONAL, + pluginId: 'playlist', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + conditions: { + anyOf: [ + playlistConditions.isOwner([ + 'user:default/me', + 'group:default/owner', + ]), + playlistConditions.isPublic(), + ], + }, + }); + }); + + it('should return a conditional decision for followers update permissions', async () => { + expect( + await policy.handle( + { permission: permissions.playlistFollowersUpdate }, + mockUser, + ), + ).toEqual({ + result: AuthorizeResult.CONDITIONAL, + pluginId: 'playlist', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + conditions: { + anyOf: [ + playlistConditions.isOwner([ + 'user:default/me', + 'group:default/owner', + ]), + playlistConditions.isPublic(), + ], + }, + }); + }); + + it('should return a conditional decision for update permissions', async () => { + expect( + await policy.handle( + { permission: permissions.playlistListUpdate }, + mockUser, + ), + ).toEqual({ + result: AuthorizeResult.CONDITIONAL, + pluginId: 'playlist', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + conditions: playlistConditions.isOwner([ + 'user:default/me', + 'group:default/owner', + ]), + }); + }); + + it('should return a conditional decision for delete permissions', async () => { + expect( + await policy.handle( + { permission: permissions.playlistListDelete }, + mockUser, + ), + ).toEqual({ + result: AuthorizeResult.CONDITIONAL, + pluginId: 'playlist', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + conditions: playlistConditions.isOwner([ + 'user:default/me', + 'group:default/owner', + ]), + }); + }); +}); diff --git a/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.ts b/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.ts new file mode 100644 index 0000000000..86d103e789 --- /dev/null +++ b/plugins/playlist-backend/src/permissions/DefaultPlaylistPermissionPolicy.ts @@ -0,0 +1,90 @@ +/* + * 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 { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; +import { + AuthorizeResult, + isPermission, + Permission, + PolicyDecision, +} from '@backstage/plugin-permission-common'; +import { + PermissionPolicy, + PolicyQuery, +} from '@backstage/plugin-permission-node'; +import { permissions } from '@backstage/plugin-playlist-common'; + +import { + createPlaylistConditionalDecision, + playlistConditions, +} from './conditions'; + +/** + * @public + */ +export const isPlaylistPermission = (permission: Permission) => + Object.values(permissions).some(playlistPermission => + isPermission(permission, playlistPermission), + ); + +/** + * Default policy for the Playlist plugin. This should be applied as a "sub-policy" + * of your master permission policy for Playlist permission requests only. + * + * @public + */ +export class DefaultPlaylistPermissionPolicy implements PermissionPolicy { + async handle( + request: PolicyQuery, + user?: BackstageIdentityResponse, + ): Promise { + // Reject permissions we don't know how to evaluate in case this policy was incorrectly applied + if (!isPlaylistPermission(request.permission)) { + return { result: AuthorizeResult.DENY }; + } + + // Anyone should be allowed to create a new playlist + if (isPermission(request.permission, permissions.playlistListCreate)) { + return { result: AuthorizeResult.ALLOW }; + } + + // Reading and following/unfollowing playlists is allowed if it is public or owned + if ( + isPermission(request.permission, permissions.playlistListRead) || + isPermission(request.permission, permissions.playlistFollowersUpdate) + ) { + return createPlaylistConditionalDecision(request.permission, { + anyOf: [ + playlistConditions.isOwner(user?.identity.ownershipEntityRefs ?? []), + playlistConditions.isPublic(), + ], + }); + } + + // Updating or deleting playlists is only allowed for owners + if ( + isPermission(request.permission, permissions.playlistListUpdate) || + isPermission(request.permission, permissions.playlistListDelete) + ) { + return createPlaylistConditionalDecision( + request.permission, + playlistConditions.isOwner(user?.identity.ownershipEntityRefs ?? []), + ); + } + + return { result: AuthorizeResult.ALLOW }; + } +} diff --git a/plugins/playlist-backend/src/permissions/conditions.ts b/plugins/playlist-backend/src/permissions/conditions.ts new file mode 100644 index 0000000000..8162c1046f --- /dev/null +++ b/plugins/playlist-backend/src/permissions/conditions.ts @@ -0,0 +1,44 @@ +/* + * 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 { PLAYLIST_LIST_RESOURCE_TYPE } from '@backstage/plugin-playlist-common'; +import { + ConditionTransformer, + createConditionExports, + createConditionTransformer, +} from '@backstage/plugin-permission-node'; + +import { ListPlaylistsFilter } from '../service'; +import { rules } from './rules'; + +const { conditions, createConditionalDecision } = createConditionExports({ + pluginId: 'playlist', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + rules, +}); + +/** + * @public + */ +export const playlistConditions = conditions; + +/** + * @public + */ +export const createPlaylistConditionalDecision = createConditionalDecision; + +export const transformConditions: ConditionTransformer = + createConditionTransformer(Object.values(rules)); diff --git a/plugins/playlist-backend/src/permissions/index.ts b/plugins/playlist-backend/src/permissions/index.ts new file mode 100644 index 0000000000..a6bb633a1e --- /dev/null +++ b/plugins/playlist-backend/src/permissions/index.ts @@ -0,0 +1,19 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './conditions'; +export * from './rules'; +export * from './DefaultPlaylistPermissionPolicy'; diff --git a/plugins/playlist-backend/src/permissions/rules.ts b/plugins/playlist-backend/src/permissions/rules.ts new file mode 100644 index 0000000000..cbf81bee65 --- /dev/null +++ b/plugins/playlist-backend/src/permissions/rules.ts @@ -0,0 +1,54 @@ +/* + * 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 { makeCreatePermissionRule } from '@backstage/plugin-permission-node'; +import { + PLAYLIST_LIST_RESOURCE_TYPE, + PlaylistMetadata, +} from '@backstage/plugin-playlist-common'; + +import { ListPlaylistsFilter } from '../service'; + +const createPlaylistPermissionRule = makeCreatePermissionRule< + PlaylistMetadata, + ListPlaylistsFilter, + typeof PLAYLIST_LIST_RESOURCE_TYPE +>(); + +const isOwner = createPlaylistPermissionRule({ + name: 'IS_OWNER', + description: 'Should allow only if the playlist belongs to the user', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + apply: (list: PlaylistMetadata, userOwnershipRefs: string[]) => + userOwnershipRefs.includes(list.owner), + toQuery: (userOwnershipRefs: string[]) => ({ + key: 'owner', + values: userOwnershipRefs, + }), +}); + +const isPublic = createPlaylistPermissionRule({ + name: 'IS_PUBLIC', + description: 'Should allow only if the playlist is public', + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + apply: (list: PlaylistMetadata) => list.public, + toQuery: () => ({ key: 'public', values: [true] }), +}); + +/** + * @public + */ +export const rules = { isOwner, isPublic }; diff --git a/plugins/playlist-backend/src/run.ts b/plugins/playlist-backend/src/run.ts new file mode 100644 index 0000000000..d945aa13f0 --- /dev/null +++ b/plugins/playlist-backend/src/run.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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/playlist-backend/src/service/DatabaseHandler.test.ts b/plugins/playlist-backend/src/service/DatabaseHandler.test.ts new file mode 100644 index 0000000000..5d6b4aa0ca --- /dev/null +++ b/plugins/playlist-backend/src/service/DatabaseHandler.test.ts @@ -0,0 +1,349 @@ +/* + * 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 { DatabaseHandler } from './DatabaseHandler'; +import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { BackstageUserIdentity } from '@backstage/plugin-auth-node'; +import { Knex } from 'knex'; +import { v4 as uuid } from 'uuid'; + +describe('DatabaseHandler', () => { + const databases = TestDatabases.create(); + + async function createDatabaseHandler(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + return { + knex, + dbHandler: await DatabaseHandler.create({ database: knex }), + }; + } + + describe.each(databases.eachSupportedId())( + '%p', + databaseId => { + let knex: Knex; + let dbHandler: DatabaseHandler; + const playlist1Id = uuid(); + const playlist2Id = uuid(); + const playlist3Id = uuid(); + const user: BackstageUserIdentity = { + type: 'user', + userEntityRef: 'user:default/foo', + ownershipEntityRefs: ['user:default/foo', 'group:default/foo-group'], + }; + + beforeEach(async () => { + ({ knex, dbHandler } = await createDatabaseHandler(databaseId)); + await knex('playlists').insert([ + { + id: playlist1Id, + name: 'test', + description: 'test description', + owner: 'user:default/foo', + public: true, + }, + { + id: playlist2Id, + name: 'test 2', + description: 'test description 2', + owner: 'group:default/foo-group', + public: false, + }, + { + id: playlist3Id, + name: 'test 3', + description: 'test description 3', + owner: 'user:default/bar', + public: false, + }, + ]); + + await knex('entities').insert([ + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent0', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent1', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent2', + }, + { + playlist_id: playlist2Id, + entity_ref: 'component:default/ent1', + }, + ]); + + await knex('followers').insert([ + { + playlist_id: playlist2Id, + user_ref: 'user:default/some-user', + }, + { + playlist_id: playlist2Id, + user_ref: 'user:default/bar', + }, + { + playlist_id: playlist2Id, + user_ref: 'user:default/foo', + }, + { + playlist_id: playlist3Id, + user_ref: 'user:default/foo', + }, + ]); + }, 30000); + + it('listPlaylists', async () => { + const allPlaylists = [ + { + id: playlist1Id, + name: 'test', + description: 'test description', + owner: 'user:default/foo', + public: true, + entities: 3, + followers: 0, + isFollowing: false, + }, + { + id: playlist2Id, + name: 'test 2', + description: 'test description 2', + owner: 'group:default/foo-group', + public: false, + entities: 1, + followers: 3, + isFollowing: true, + }, + { + id: playlist3Id, + name: 'test 3', + description: 'test description 3', + owner: 'user:default/bar', + public: false, + entities: 0, + followers: 1, + isFollowing: true, + }, + ]; + + const playlists = await dbHandler.listPlaylists(user); + expect(playlists.length).toEqual(3); + expect(playlists).toEqual(expect.arrayContaining(allPlaylists)); + + const followedPlaylists = await dbHandler.listPlaylists(user, { + key: 'public', + values: [true], + }); + expect(followedPlaylists).toEqual([allPlaylists[0]]); + + const ownedPlaylists = await dbHandler.listPlaylists(user, { + key: 'owner', + values: user.ownershipEntityRefs, + }); + expect(ownedPlaylists.length).toEqual(2); + expect(ownedPlaylists).toEqual( + expect.arrayContaining([allPlaylists[0], allPlaylists[1]]), + ); + }); + + it('createPlaylist', async () => { + const newList = { + name: 'new list', + description: 'new description', + owner: 'user:default/new', + public: true, + }; + + const newPlaylistId = await dbHandler.createPlaylist(newList); + + const newPlaylist = await knex('playlists').where('id', newPlaylistId); + expect( + newPlaylist.map(list => ({ ...list, public: Boolean(list.public) })), + ).toEqual([ + { + ...newList, + id: newPlaylistId, + }, + ]); + }); + + it('getPlaylist', async () => { + const playlist = await dbHandler.getPlaylist(playlist1Id, user); + expect(playlist).toEqual({ + id: playlist1Id, + name: 'test', + description: 'test description', + owner: 'user:default/foo', + public: true, + entities: 3, + followers: 0, + isFollowing: false, + }); + }); + + it('updatePlaylist', async () => { + const update = { + id: playlist1Id, + name: 'test rename', + description: 'test new description', + owner: 'user:default/new-foo', + public: false, + }; + await dbHandler.updatePlaylist(update); + + const updatedPlaylist = await knex('playlists').where( + 'id', + playlist1Id, + ); + expect( + updatedPlaylist.map(list => ({ + ...list, + public: Boolean(list.public), + })), + ).toEqual([update]); + }); + + it('deletePlaylist', async () => { + await dbHandler.deletePlaylist(playlist1Id); + const deleted = await knex('playlists').where('id', playlist1Id); + expect(deleted.length).toEqual(0); + }); + + it('addPlaylistEntities', async () => { + await dbHandler.addPlaylistEntities(playlist1Id, [ + 'component:default/ent1', + 'component:default/ent3', + 'component:default/ent4', + ]); + + const entities = await knex('entities').where( + 'playlist_id', + playlist1Id, + ); + expect(entities.length).toEqual(5); + expect(entities).toEqual( + expect.arrayContaining([ + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent0', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent1', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent2', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent3', + }, + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent4', + }, + ]), + ); + }); + + it('getPlaylistEntities', async () => { + const entities = await dbHandler.getPlaylistEntities(playlist1Id); + expect(entities.length).toEqual(3); + expect(entities).toEqual( + expect.arrayContaining([ + 'component:default/ent0', + 'component:default/ent1', + 'component:default/ent2', + ]), + ); + }); + + it('removePlaylistEntities', async () => { + await dbHandler.removePlaylistEntities(playlist1Id, [ + 'component:default/ent1', + 'component:default/ent2', + ]); + + const entities = await knex('entities').where( + 'playlist_id', + playlist1Id, + ); + expect(entities).toEqual([ + { + playlist_id: playlist1Id, + entity_ref: 'component:default/ent0', + }, + ]); + }); + + it('followPlaylist', async () => { + await dbHandler.followPlaylist(playlist1Id, user); + + const playlist1Followers = await knex('followers').where( + 'playlist_id', + playlist1Id, + ); + expect(playlist1Followers).toEqual([ + { + playlist_id: playlist1Id, + user_ref: 'user:default/foo', + }, + ]); + + await dbHandler.followPlaylist(playlist3Id, user); + + const playlist3Followers = await knex('followers').where( + 'playlist_id', + playlist3Id, + ); + expect(playlist3Followers).toEqual([ + { + playlist_id: playlist3Id, + user_ref: 'user:default/foo', + }, + ]); + }); + + it('unfollowPlaylist', async () => { + await dbHandler.unfollowPlaylist(playlist2Id, user); + + const followers = await knex('followers').where( + 'playlist_id', + playlist2Id, + ); + expect(followers).toEqual( + expect.arrayContaining([ + { + playlist_id: playlist2Id, + user_ref: 'user:default/some-user', + }, + { + playlist_id: playlist2Id, + user_ref: 'user:default/bar', + }, + ]), + ); + }); + }, + 60000, + ); +}); diff --git a/plugins/playlist-backend/src/service/DatabaseHandler.ts b/plugins/playlist-backend/src/service/DatabaseHandler.ts new file mode 100644 index 0000000000..6118f22ff9 --- /dev/null +++ b/plugins/playlist-backend/src/service/DatabaseHandler.ts @@ -0,0 +1,278 @@ +/* + * 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 { resolvePackagePath } from '@backstage/backend-common'; +import { BackstageUserIdentity } from '@backstage/plugin-auth-node'; +import { Playlist, PlaylistMetadata } from '@backstage/plugin-playlist-common'; +import { Knex } from 'knex'; +import { v4 as uuid } from 'uuid'; + +import { + ListPlaylistsFilter, + ListPlaylistsMatchFilter, +} from './ListPlaylistsFilter'; + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-playlist-backend', + 'migrations', +); + +function isMatchFilter( + filter: ListPlaylistsMatchFilter | ListPlaylistsFilter, +): filter is ListPlaylistsMatchFilter { + return filter.hasOwnProperty('key'); +} + +function isOrFilter( + filter: { anyOf: ListPlaylistsFilter[] } | ListPlaylistsFilter, +): filter is { anyOf: ListPlaylistsFilter[] } { + return filter.hasOwnProperty('anyOf'); +} + +function isNegationFilter( + filter: { not: ListPlaylistsFilter } | ListPlaylistsFilter, +): filter is { not: ListPlaylistsFilter } { + return filter.hasOwnProperty('not'); +} + +function parseFilter( + filter: ListPlaylistsFilter, + query: Knex.QueryBuilder, + db: Knex, + negate: boolean = false, +): Knex.QueryBuilder { + if (isMatchFilter(filter)) { + return query.andWhere(function filterFunction() { + if (filter.values.length === 1) { + this.where(filter.key, negate ? '!=' : '=', filter.values[0]); + } else { + this.andWhere(filter.key, negate ? 'not in' : 'in', filter.values); + } + }); + } + + if (isNegationFilter(filter)) { + return parseFilter(filter.not, query, db, !negate); + } + + return query[negate ? 'andWhereNot' : 'andWhere'](function filterFunction() { + if (isOrFilter(filter)) { + for (const subFilter of filter.anyOf ?? []) { + this.orWhere(subQuery => parseFilter(subFilter, subQuery, db)); + } + } else { + for (const subFilter of filter.allOf ?? []) { + this.andWhere(subQuery => parseFilter(subFilter, subQuery, db)); + } + } + }); +} + +type Options = { + database: Knex; +}; + +/** + * @public + */ +export class DatabaseHandler { + static async create(options: Options): Promise { + const { database } = options; + + await database.migrate.latest({ + directory: migrationsDir, + }); + + return new DatabaseHandler(options); + } + + private readonly database: Knex; + + private constructor(options: Options) { + this.database = options.database; + } + + private playlistColumns = ['id', 'name', 'description', 'owner', 'public']; + + async listPlaylists( + user: BackstageUserIdentity, + filter?: ListPlaylistsFilter, + ): Promise { + let playlistQuery = this.database>( + 'playlists', + ) + .select( + ...this.playlistColumns, + this.database.raw('COALESCE(entities, 0) AS entities'), + this.database.raw('COALESCE(followers, 0) AS followers'), + ) + .leftOuterJoin( + this.database('entities') + .as('e') + .select('playlist_id') + .count('entity_ref', { as: 'entities' }) + .groupBy('playlist_id'), + 'playlists.id', + 'e.playlist_id', + ) + .leftOuterJoin( + this.database('followers') + .as('f') + .select('playlist_id') + .count('user_ref', { as: 'followers' }) + .groupBy('playlist_id'), + 'playlists.id', + 'f.playlist_id', + ); + + if (filter) { + playlistQuery = parseFilter(filter, playlistQuery, this.database); + } + + const playlists = await playlistQuery; + + const followedPlaylists = ( + await this.database('followers') + .select('playlist_id') + .where('user_ref', user.userEntityRef) + ).map(follows => follows.playlist_id); + + return playlists.map(list => ({ + ...list, + entities: Number(list.entities), + followers: Number(list.followers), + public: Boolean(list.public), + isFollowing: followedPlaylists.includes(list.id), + })); + } + + async createPlaylist( + playlist: Omit, + ): Promise { + const id = uuid(); + const newPlaylist = await this.database('playlists').insert( + { + ...playlist, + id, + }, + ['id'], + ); + + // MySQL does not support returning from inserts so return generated uuid if undefined + return newPlaylist[0].id ?? id; + } + + async getPlaylist( + id: string, + user?: BackstageUserIdentity, + ): Promise { + const playlist = await this.database>( + 'playlists', + ) + .select( + ...this.playlistColumns, + this.database.raw('COALESCE(entities, 0) AS entities'), + this.database.raw('COALESCE(followers, 0) AS followers'), + ) + .where('id', id) + .leftOuterJoin( + this.database('entities') + .as('e') + .select('playlist_id') + .count('entity_ref', { as: 'entities' }) + .groupBy('playlist_id'), + 'playlists.id', + 'e.playlist_id', + ) + .leftOuterJoin( + this.database('followers') + .as('f') + .select('playlist_id') + .count('user_ref', { as: 'followers' }) + .groupBy('playlist_id'), + 'playlists.id', + 'f.playlist_id', + ); + + if (!playlist.length) { + return undefined; + } + + const followedPlaylists = user + ? ( + await this.database('followers') + .select('playlist_id') + .where('user_ref', user.userEntityRef) + ).map(follows => follows.playlist_id) + : []; + + return { + ...playlist[0], + entities: Number(playlist[0].entities), + followers: Number(playlist[0].followers), + public: Boolean(playlist[0].public), + isFollowing: followedPlaylists.includes(playlist[0].id), + }; + } + + async updatePlaylist(playlist: PlaylistMetadata) { + await this.database('playlists').where('id', playlist.id).update(playlist); + } + + async deletePlaylist(id: string) { + await this.database('playlists').where('id', id).del(); + } + + async addPlaylistEntities(playlistId: string, entityRefs: string[]) { + await this.database('entities') + .insert( + entityRefs.map(ref => ({ playlist_id: playlistId, entity_ref: ref })), + ) + .onConflict(['playlist_id', 'entity_ref']) + .ignore(); + } + + async getPlaylistEntities(playlistId: string): Promise { + return ( + await this.database('entities') + .select('entity_ref') + .where('playlist_id', playlistId) + ).map(entity => entity.entity_ref); + } + + async removePlaylistEntities(playlistId: string, entityRefs: string[]) { + await this.database('entities') + .where(builder => + entityRefs.forEach(ref => + builder.orWhere({ playlist_id: playlistId, entity_ref: ref }), + ), + ) + .del(); + } + + async followPlaylist(playlistId: string, user: BackstageUserIdentity) { + await this.database('followers') + .insert({ playlist_id: playlistId, user_ref: user.userEntityRef }) + .onConflict(['playlist_id', 'user_ref']) + .ignore(); + } + + async unfollowPlaylist(playlistId: string, user: BackstageUserIdentity) { + await this.database('followers') + .where({ playlist_id: playlistId, user_ref: user.userEntityRef }) + .del(); + } +} diff --git a/plugins/playlist-backend/src/service/ListPlaylistsFilter.test.ts b/plugins/playlist-backend/src/service/ListPlaylistsFilter.test.ts new file mode 100644 index 0000000000..64405fa6d0 --- /dev/null +++ b/plugins/playlist-backend/src/service/ListPlaylistsFilter.test.ts @@ -0,0 +1,95 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + parseListPlaylistsFilterParams, + parseListPlaylistsFilterString, +} from './ListPlaylistsFilter'; + +describe('parseListPlaylistsFilterParams', () => { + it('translates empty query to empty list', () => { + const result = parseListPlaylistsFilterParams({}); + expect(result).toEqual(undefined); + }); + + it('supports single-string format', () => { + const result = parseListPlaylistsFilterParams({ filter: 'a=1' })!; + expect(result).toEqual({ + anyOf: [{ allOf: [{ key: 'a', values: ['1'] }] }], + }); + }); + + it('supports array-of-strings format', () => { + const result = parseListPlaylistsFilterParams({ + filter: ['a=1', 'b=2'], + }); + expect(result).toEqual({ + anyOf: [ + { allOf: [{ key: 'a', values: ['1'] }] }, + { allOf: [{ key: 'b', values: ['2'] }] }, + ], + }); + }); + + it('merges values within each filter', () => { + const result = parseListPlaylistsFilterParams({ + filter: ['a=1', 'b=2,b=3,c=4'], + }); + expect(result).toEqual({ + anyOf: [ + { allOf: [{ key: 'a', values: ['1'] }] }, + { + allOf: [ + { key: 'b', values: ['2', '3'] }, + { key: 'c', values: ['4'] }, + ], + }, + ], + }); + }); + + it('throws for non-strings', () => { + expect(() => parseListPlaylistsFilterParams({ filter: [3] })).toThrow( + 'Invalid filter', + ); + }); +}); + +describe('parseListPlaylistsFilterString', () => { + it('works for the happy path', () => { + expect(parseListPlaylistsFilterString('')).toBeUndefined(); + expect(parseListPlaylistsFilterString('a=1,b=2,a=3')).toEqual([ + { key: 'a', values: ['1', '3'] }, + { key: 'b', values: ['2'] }, + ]); + }); + + it('trims values', () => { + expect(parseListPlaylistsFilterString(' a = 1 , b = 2 , a = 3 ')).toEqual([ + { key: 'a', values: ['1', '3'] }, + { key: 'b', values: ['2'] }, + ]); + }); + + it('rejects malformed strings', () => { + expect(() => parseListPlaylistsFilterString('x=2,=a')).toThrow( + "Invalid filter, '=a' is not a valid statement (expected a string of the form a=b)", + ); + expect(() => parseListPlaylistsFilterString('x=2,a=')).toThrow( + "Invalid filter, 'a=' is not a valid statement (expected a string of the form a=b)", + ); + }); +}); diff --git a/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts b/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts new file mode 100644 index 0000000000..bff14b2a58 --- /dev/null +++ b/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts @@ -0,0 +1,101 @@ +/* + * 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 { InputError } from '@backstage/errors'; + +// TODO(kuangp): this filter shape was basically plagiarized from catalog-backend, +// it should probably be abstracted into a common plugin module to allow others to reuse the same pattern + +/** + * @public + */ +export type ListPlaylistsMatchFilter = { + key: string; + values: any[]; +}; + +/** + * @public + */ +export type ListPlaylistsFilter = + | { allOf: ListPlaylistsFilter[] } + | { anyOf: ListPlaylistsFilter[] } + | { not: ListPlaylistsFilter } + | ListPlaylistsMatchFilter; + +export function parseListPlaylistsFilterParams( + params: Record, +): ListPlaylistsFilter | undefined { + if (!params.filter) { + return undefined; + } + + // Each filter string is on the form a=b,c=d + const filterStrings = [params.filter].flat(); + if (filterStrings.some(p => typeof p !== 'string')) { + throw new InputError('Invalid filter'); + } + + // Outer array: "any of the inner ones" + // Inner arrays: "all of these must match" + const filters = (filterStrings as string[]) + .map(parseListPlaylistsFilterString) + .filter(Boolean); + if (!filters.length) { + return undefined; + } + + return { anyOf: filters.map(f => ({ allOf: f! })) }; +} + +export function parseListPlaylistsFilterString( + filterString: string, +): ListPlaylistsMatchFilter[] | undefined { + const statements = filterString + .split(',') + .map(s => s.trim()) + .filter(Boolean); + + if (!statements.length) { + return undefined; + } + + const filtersByKey: Record = {}; + + for (const statement of statements) { + const equalsIndex = statement.indexOf('='); + + const key = + equalsIndex === -1 ? statement : statement.substr(0, equalsIndex).trim(); + const value = + equalsIndex === -1 ? undefined : statement.substr(equalsIndex + 1).trim(); + + if (!key || !value) { + throw new InputError( + `Invalid filter, '${statement}' is not a valid statement (expected a string of the form a=b)`, + ); + } + + const f = + key in filtersByKey + ? filtersByKey[key] + : (filtersByKey[key] = { key, values: [] }); + + f.values.push(value); + } + + return Object.values(filtersByKey); +} diff --git a/plugins/playlist-backend/src/service/index.ts b/plugins/playlist-backend/src/service/index.ts new file mode 100644 index 0000000000..3a1499f495 --- /dev/null +++ b/plugins/playlist-backend/src/service/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './router'; +export type { + ListPlaylistsFilter, + ListPlaylistsMatchFilter, +} from './ListPlaylistsFilter'; diff --git a/plugins/playlist-backend/src/service/router.test.ts b/plugins/playlist-backend/src/service/router.test.ts new file mode 100644 index 0000000000..06185acae8 --- /dev/null +++ b/plugins/playlist-backend/src/service/router.test.ts @@ -0,0 +1,511 @@ +/* + * 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 { DatabaseManager, getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { permissions } from '@backstage/plugin-playlist-common'; +import express from 'express'; +import request from 'supertest'; + +import { createRouter } from './router'; + +jest.mock('@backstage/plugin-auth-node', () => ({ + ...jest.requireActual('@backstage/plugin-auth-node'), + getBearerTokenFromAuthorizationHeader: () => 'token', +})); + +const mockConditionFilter = { key: 'test', values: ['test-val'] }; +jest.mock('../permissions', () => ({ + ...jest.requireActual('../permissions'), + transformConditions: () => mockConditionFilter, +})); + +const mockPlaylist = { + id: 'playlist-id', + name: 'test-playlist', + owner: 'group:default/owner', + public: true, + entities: 2, + followers: 4, + isFollowing: false, +}; + +const mockEntities = [ + 'component:default/test-ent', + 'system:default/test-ent-system', +]; + +const mockDbHandler = { + listPlaylists: jest.fn().mockImplementation(async () => [mockPlaylist]), + createPlaylist: jest.fn().mockImplementation(async () => 'playlist-id'), + getPlaylist: jest.fn().mockImplementation(async () => mockPlaylist), + updatePlaylist: jest.fn().mockImplementation(async () => {}), + deletePlaylist: jest.fn().mockImplementation(async () => {}), + addPlaylistEntities: jest.fn().mockImplementation(async () => {}), + getPlaylistEntities: jest.fn().mockImplementation(async () => mockEntities), + removePlaylistEntities: jest.fn().mockImplementation(async () => {}), + followPlaylist: jest.fn().mockImplementation(async () => {}), + unfollowPlaylist: jest.fn().mockImplementation(async () => {}), +}; + +jest.mock('./DatabaseHandler', () => ({ + DatabaseHandler: { create: async () => mockDbHandler }, +})); + +describe('createRouter', () => { + let app: express.Express; + + const createDatabase = () => + DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'better-sqlite3', + connection: ':memory:', + }, + }, + }), + ).forPlugin('playlist'); + + const mockedAuthorize = jest + .fn() + .mockImplementation(async () => [{ result: AuthorizeResult.ALLOW }]); + const mockedAuthorizeConditional = jest + .fn() + .mockImplementation(async () => [{ result: AuthorizeResult.ALLOW }]); + const mockPermissionEvaluator = { + authorize: mockedAuthorize, + authorizeConditional: mockedAuthorizeConditional, + }; + + const mockUser = { + type: 'user', + ownershipEntityRefs: ['user:default/me', 'group:default/owner'], + userEntityRef: 'user:default/me', + }; + const mockIdentityClient = { + authenticate: jest + .fn() + .mockImplementation(async () => ({ identity: mockUser })), + } as unknown as IdentityClient; + + beforeEach(async () => { + const router = await createRouter({ + database: createDatabase(), + identity: mockIdentityClient, + logger: getVoidLogger(), + permissions: mockPermissionEvaluator, + }); + + app = express().use(router); + jest.clearAllMocks(); + }); + + describe('GET /', () => { + const mockRequestFilter = { + anyOf: [ + { allOf: [{ key: 'mock', values: ['test'] }] }, + { allOf: [{ key: 'foo', values: ['bar'] }] }, + ], + }; + + it('should respond correctly if unauthorized', async () => { + mockedAuthorizeConditional.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).get('/').send(); + + expect(mockedAuthorizeConditional).toHaveBeenCalledWith( + [{ permission: permissions.playlistListRead }], + { token: 'token' }, + ); + expect(mockDbHandler.listPlaylists).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should get playlists correctly', async () => { + let response = await request(app).get('/').send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith( + mockUser, + undefined, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + + mockedAuthorizeConditional.mockImplementationOnce(async () => [ + { result: AuthorizeResult.CONDITIONAL }, + ]); + response = await request(app).get('/').send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith( + mockUser, + mockConditionFilter, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + }); + + it('should get filtered playlists correctly', async () => { + let response = await request(app) + .get('/?filter=mock=test&filter=foo=bar') + .send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith( + mockUser, + mockRequestFilter, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + + mockedAuthorizeConditional.mockImplementationOnce(async () => [ + { result: AuthorizeResult.CONDITIONAL }, + ]); + response = await request(app) + .get('/?filter=mock=test&filter=foo=bar') + .send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith(mockUser, { + allOf: [mockRequestFilter, mockConditionFilter], + }); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + }); + + it('should get editable playlists correctly', async () => { + let response = await request(app).get('/?editable=true').send(); + expect(mockedAuthorizeConditional).toHaveBeenCalledWith( + [{ permission: permissions.playlistListUpdate }], + { token: 'token' }, + ); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith( + mockUser, + undefined, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + + response = await request(app) + .get('/?editable=true&filter=mock=test&filter=foo=bar') + .send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith( + mockUser, + mockRequestFilter, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + + mockedAuthorizeConditional.mockImplementation(async () => [ + { result: AuthorizeResult.CONDITIONAL }, + ]); + response = await request(app).get('/?editable=true').send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith(mockUser, { + allOf: [mockConditionFilter, mockConditionFilter], + }); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + + mockedAuthorizeConditional.mockImplementation(async () => [ + { result: AuthorizeResult.CONDITIONAL }, + ]); + response = await request(app) + .get('/?editable=true&filter=mock=test&filter=foo=bar') + .send(); + expect(mockDbHandler.listPlaylists).toHaveBeenLastCalledWith(mockUser, { + allOf: [ + { allOf: [mockRequestFilter, mockConditionFilter] }, + mockConditionFilter, + ], + }); + expect(response.status).toEqual(200); + expect(response.body).toEqual([mockPlaylist]); + }); + }); + + describe('POST /', () => { + const body = { name: 'new-playlist' }; + + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).post('/').send(body); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [{ permission: permissions.playlistListCreate }], + { token: 'token' }, + ); + expect(mockDbHandler.createPlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should create a playlist correctly', async () => { + const response = await request(app).post('/').send(body); + expect(mockDbHandler.createPlaylist).toHaveBeenCalledWith(body); + expect(response.status).toEqual(201); + expect(response.body).toEqual('playlist-id'); + }); + }); + + describe('GET /:playlistId', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).get('/playlist-id').send(); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListRead, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.getPlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should get a playlist correctly', async () => { + const response = await request(app).get('/playlist-id').send(); + expect(mockDbHandler.getPlaylist).toHaveBeenCalledWith( + 'playlist-id', + mockUser, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual(mockPlaylist); + }); + }); + + describe('PUT /:playlistId', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app) + .put('/playlist-id') + .send(mockPlaylist); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListUpdate, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.updatePlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should update a playlist correctly', async () => { + const response = await request(app) + .put('/playlist-id') + .send(mockPlaylist); + expect(mockDbHandler.updatePlaylist).toHaveBeenCalledWith(mockPlaylist); + expect(response.status).toEqual(200); + }); + }); + + describe('DELETE /:playlistId', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).delete('/playlist-id').send(); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListDelete, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.deletePlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should delete a playlist correctly', async () => { + const response = await request(app).delete('/playlist-id').send(); + expect(mockDbHandler.deletePlaylist).toHaveBeenCalledWith('playlist-id'); + expect(response.status).toEqual(200); + }); + }); + + describe('POST /:playlistId/entities', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app) + .post('/playlist-id/entities') + .send(['component:default/test-ent']); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListUpdate, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.addPlaylistEntities).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should add entities to a playlist correctly', async () => { + const response = await request(app) + .post('/playlist-id/entities') + .send(mockEntities); + expect(mockDbHandler.addPlaylistEntities).toHaveBeenCalledWith( + 'playlist-id', + mockEntities, + ); + expect(response.status).toEqual(200); + }); + }); + + describe('GET /:playlistId/entities', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).get('/playlist-id/entities').send(); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListRead, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.getPlaylistEntities).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should get entities from a playlist correctly', async () => { + const response = await request(app).get('/playlist-id/entities').send(); + expect(mockDbHandler.getPlaylistEntities).toHaveBeenCalledWith( + 'playlist-id', + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual(mockEntities); + }); + }); + + describe('DELETE /:playlistId/entities', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app) + .delete('/playlist-id/entities') + .send(mockEntities); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistListUpdate, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.removePlaylistEntities).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should delete entities from a playlist correctly', async () => { + const response = await request(app) + .delete('/playlist-id/entities') + .send(mockEntities); + expect(mockDbHandler.removePlaylistEntities).toHaveBeenCalledWith( + 'playlist-id', + mockEntities, + ); + expect(response.status).toEqual(200); + }); + }); + + describe('POST /:playlistId/followers', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app).post('/playlist-id/followers').send(); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistFollowersUpdate, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.followPlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should follow a playlist correctly', async () => { + const response = await request(app).post('/playlist-id/followers').send(); + expect(mockDbHandler.followPlaylist).toHaveBeenCalledWith( + 'playlist-id', + mockUser, + ); + expect(response.status).toEqual(200); + }); + }); + + describe('DELETE /:playlistId/followers', () => { + it('should respond correctly if unauthorized', async () => { + mockedAuthorize.mockImplementationOnce(async () => [ + { result: AuthorizeResult.DENY }, + ]); + const response = await request(app) + .delete('/playlist-id/followers') + .send(); + + expect(mockedAuthorize).toHaveBeenCalledWith( + [ + { + permission: permissions.playlistFollowersUpdate, + resourceRef: 'playlist-id', + }, + ], + { token: 'token' }, + ); + expect(mockDbHandler.unfollowPlaylist).not.toHaveBeenCalled(); + expect(response.status).toEqual(403); + }); + + it('should unfollow a playlist correctly', async () => { + const response = await request(app) + .delete('/playlist-id/followers') + .send(); + expect(mockDbHandler.unfollowPlaylist).toHaveBeenCalledWith( + 'playlist-id', + mockUser, + ); + expect(response.status).toEqual(200); + }); + }); +}); diff --git a/plugins/playlist-backend/src/service/router.ts b/plugins/playlist-backend/src/service/router.ts new file mode 100644 index 0000000000..7ca41c0ac1 --- /dev/null +++ b/plugins/playlist-backend/src/service/router.ts @@ -0,0 +1,232 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { errorHandler, PluginDatabaseManager } from '@backstage/backend-common'; +import { NotAllowedError } from '@backstage/errors'; +import { + getBearerTokenFromAuthorizationHeader, + IdentityClient, +} from '@backstage/plugin-auth-node'; +import { + AuthorizePermissionRequest, + AuthorizeResult, + PermissionEvaluator, + QueryPermissionRequest, +} from '@backstage/plugin-permission-common'; +import { createPermissionIntegrationRouter } from '@backstage/plugin-permission-node'; +import { + PLAYLIST_LIST_RESOURCE_TYPE, + permissions, +} from '@backstage/plugin-playlist-common'; +import express from 'express'; +import Router from 'express-promise-router'; +import { Logger } from 'winston'; + +import { rules, transformConditions } from '../permissions'; +import { DatabaseHandler } from './DatabaseHandler'; +import { parseListPlaylistsFilterParams } from './ListPlaylistsFilter'; + +/** + * @public + */ +export interface RouterOptions { + database: PluginDatabaseManager; + identity: IdentityClient; + logger: Logger; + permissions: PermissionEvaluator; +} + +/** + * @public + */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { + database, + identity, + logger, + permissions: permissionEvaluator, + } = options; + + logger.info('Initializing Playlist backend'); + + const db = await database.getClient(); + const dbHandler = await DatabaseHandler.create({ database: db }); + + const evaluateRequestPermission = async ( + req: express.Request, + permission: AuthorizePermissionRequest | QueryPermissionRequest, + conditional: boolean = false, + ) => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + const user = await identity.authenticate(token); + + const decision = conditional + ? ( + await permissionEvaluator.authorizeConditional( + [permission as QueryPermissionRequest], + { token }, + ) + )[0] + : ( + await permissionEvaluator.authorize( + [permission as AuthorizePermissionRequest], + { token }, + ) + )[0]; + + if (decision.result === AuthorizeResult.DENY) { + throw new NotAllowedError('Unauthorized'); + } + + return { decision, user: user.identity }; + }; + + const permissionIntegrationRouter = createPermissionIntegrationRouter({ + getResources: resourceRefs => + Promise.all(resourceRefs.map(ref => dbHandler.getPlaylist(ref))), + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, + rules: Object.values(rules), + }); + + const router = Router(); + router.use(express.json()); + router.use(permissionIntegrationRouter); + + router.get('/', async (req, res) => { + const { decision, user } = await evaluateRequestPermission( + req, + { permission: permissions.playlistListRead }, + true, + ); + + let filter = parseListPlaylistsFilterParams(req.query); + if (decision.result === AuthorizeResult.CONDITIONAL) { + const conditionsFilter = transformConditions(decision.conditions); + filter = filter + ? { allOf: [filter, conditionsFilter] } + : conditionsFilter; + } + + if (req.query.editable) { + const { decision: updatePermissionDecision } = + await evaluateRequestPermission( + req, + { permission: permissions.playlistListUpdate }, + true, + ); + + if (updatePermissionDecision.result === AuthorizeResult.CONDITIONAL) { + const updateConditionsFilter = transformConditions( + updatePermissionDecision.conditions, + ); + filter = filter + ? { allOf: [filter, updateConditionsFilter] } + : updateConditionsFilter; + } + } + + const playlists = await dbHandler.listPlaylists(user, filter); + res.json(playlists); + }); + + router.post('/', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListCreate, + }); + const playlistId = await dbHandler.createPlaylist(req.body); + res.status(201).json(playlistId); + }); + + router.get('/:playlistId', async (req, res) => { + const { user } = await evaluateRequestPermission(req, { + permission: permissions.playlistListRead, + resourceRef: req.params.playlistId, + }); + const playlist = await dbHandler.getPlaylist(req.params.playlistId, user); + res.json(playlist); + }); + + router.put('/:playlistId', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListUpdate, + resourceRef: req.params.playlistId, + }); + await dbHandler.updatePlaylist({ ...req.body, id: req.params.playlistId }); + res.status(200).end(); + }); + + router.delete('/:playlistId', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListDelete, + resourceRef: req.params.playlistId, + }); + await dbHandler.deletePlaylist(req.params.playlistId); + res.status(200).end(); + }); + + router.post('/:playlistId/entities', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListUpdate, + resourceRef: req.params.playlistId, + }); + await dbHandler.addPlaylistEntities(req.params.playlistId, req.body); + res.status(200).end(); + }); + + router.get('/:playlistId/entities', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListRead, + resourceRef: req.params.playlistId, + }); + const entities = await dbHandler.getPlaylistEntities(req.params.playlistId); + res.json(entities); + }); + + router.delete('/:playlistId/entities', async (req, res) => { + await evaluateRequestPermission(req, { + permission: permissions.playlistListUpdate, + resourceRef: req.params.playlistId, + }); + await dbHandler.removePlaylistEntities(req.params.playlistId, req.body); + res.status(200).end(); + }); + + router.post('/:playlistId/followers', async (req, res) => { + const { user } = await evaluateRequestPermission(req, { + permission: permissions.playlistFollowersUpdate, + resourceRef: req.params.playlistId, + }); + await dbHandler.followPlaylist(req.params.playlistId, user); + res.status(200).end(); + }); + + router.delete('/:playlistId/followers', async (req, res) => { + const { user } = await evaluateRequestPermission(req, { + permission: permissions.playlistFollowersUpdate, + resourceRef: req.params.playlistId, + }); + await dbHandler.unfollowPlaylist(req.params.playlistId, user); + res.status(200).end(); + }); + + router.use(errorHandler()); + return router; +} diff --git a/plugins/playlist-backend/src/service/standaloneServer.ts b/plugins/playlist-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..46d6f7ad8d --- /dev/null +++ b/plugins/playlist-backend/src/service/standaloneServer.ts @@ -0,0 +1,90 @@ +/* + * 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 { + createServiceBuilder, + DatabaseManager, + loadBackendConfig, + ServerTokenManager, + SingleHostDiscovery, + useHotMemoize, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { ServerPermissionClient } from '@backstage/plugin-permission-node'; +import { Server } from 'http'; +import { Logger } from 'winston'; +import { createRouter } from './router'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'playlist-backend' }); + const config = await loadBackendConfig({ logger, argv: process.argv }); + const discovery = SingleHostDiscovery.fromConfig(config); + + const database = useHotMemoize(module, () => { + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + return manager.forPlugin('playlist'); + }); + + const identity = IdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + }); + + const tokenManager = ServerTokenManager.fromConfig(config, { + logger, + }); + const permissions = ServerPermissionClient.fromConfig(config, { + discovery, + tokenManager, + }); + + logger.debug('Starting application server...'); + const router = await createRouter({ + database, + identity, + logger, + permissions, + }); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/playlist', router); + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/playlist-backend/src/setupTests.ts b/plugins/playlist-backend/src/setupTests.ts new file mode 100644 index 0000000000..813cdeaae3 --- /dev/null +++ b/plugins/playlist-backend/src/setupTests.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 {}; diff --git a/plugins/playlist-common/.eslintrc.js b/plugins/playlist-common/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/playlist-common/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/playlist-common/README.md b/plugins/playlist-common/README.md new file mode 100644 index 0000000000..72f502386c --- /dev/null +++ b/plugins/playlist-common/README.md @@ -0,0 +1,3 @@ +# Playlist Common + +Common functionalities, types, and permissions for the playlist plugin. diff --git a/plugins/playlist-common/api-report.md b/plugins/playlist-common/api-report.md new file mode 100644 index 0000000000..e97cb3dc64 --- /dev/null +++ b/plugins/playlist-common/api-report.md @@ -0,0 +1,36 @@ +## API Report File for "@backstage/plugin-playlist-common" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BasicPermission } from '@backstage/plugin-permission-common'; +import { ResourcePermission } from '@backstage/plugin-permission-common'; + +// @public (undocumented) +export const permissions: { + playlistListCreate: BasicPermission; + playlistListRead: ResourcePermission<'playlist-list'>; + playlistListUpdate: ResourcePermission<'playlist-list'>; + playlistListDelete: ResourcePermission<'playlist-list'>; + playlistFollowersUpdate: ResourcePermission<'playlist-list'>; +}; + +// @public (undocumented) +export type Playlist = PlaylistMetadata & { + entities: number; + followers: number; + isFollowing: boolean; +}; + +// @public (undocumented) +export const PLAYLIST_LIST_RESOURCE_TYPE = 'playlist-list'; + +// @public (undocumented) +export type PlaylistMetadata = { + id: string; + name: string; + description?: string; + owner: string; + public: boolean; +}; +``` diff --git a/plugins/playlist-common/package.json b/plugins/playlist-common/package.json new file mode 100644 index 0000000000..67a97b1237 --- /dev/null +++ b/plugins/playlist-common/package.json @@ -0,0 +1,34 @@ +{ + "name": "@backstage/plugin-playlist-common", + "description": "Common functionalities for the playlist plugin", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "common-library" + }, + "scripts": { + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/plugin-permission-common": "^0.6.4-next.1" + }, + "devDependencies": { + "@backstage/cli": "^0.19.0-next.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/playlist-common/src/index.ts b/plugins/playlist-common/src/index.ts new file mode 100644 index 0000000000..92cf1eb461 --- /dev/null +++ b/plugins/playlist-common/src/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Common functionalities for the playlist plugin. + * + * @packageDocumentation + */ + +export * from './types'; +export * from './permissions'; diff --git a/plugins/playlist-common/src/permissions.ts b/plugins/playlist-common/src/permissions.ts new file mode 100644 index 0000000000..89d526127e --- /dev/null +++ b/plugins/playlist-common/src/permissions.ts @@ -0,0 +1,62 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createPermission } from '@backstage/plugin-permission-common'; + +/** + * @public + */ +export const PLAYLIST_LIST_RESOURCE_TYPE = 'playlist-list'; + +const playlistListCreate = createPermission({ + name: 'playlist.list.create', + attributes: { action: 'create' }, +}); + +const playlistListRead = createPermission({ + name: 'playlist.list.read', + attributes: { action: 'read' }, + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, +}); + +const playlistListUpdate = createPermission({ + name: 'playlist.list.update', + attributes: { action: 'update' }, + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, +}); + +const playlistListDelete = createPermission({ + name: 'playlist.list.delete', + attributes: { action: 'delete' }, + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, +}); + +const playlistFollowersUpdate = createPermission({ + name: 'playlist.followers.update', + attributes: { action: 'update' }, + resourceType: PLAYLIST_LIST_RESOURCE_TYPE, +}); + +/** + * @public + */ +export const permissions = { + playlistListCreate, + playlistListRead, + playlistListUpdate, + playlistListDelete, + playlistFollowersUpdate, +}; diff --git a/plugins/playlist-common/src/setupTests.ts b/plugins/playlist-common/src/setupTests.ts new file mode 100644 index 0000000000..8b9b6bd586 --- /dev/null +++ b/plugins/playlist-common/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export {}; diff --git a/plugins/playlist-common/src/types.ts b/plugins/playlist-common/src/types.ts new file mode 100644 index 0000000000..667cd35ece --- /dev/null +++ b/plugins/playlist-common/src/types.ts @@ -0,0 +1,35 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @public + */ +export type PlaylistMetadata = { + id: string; + name: string; + description?: string; + owner: string; + public: boolean; +}; + +/** + * @public + */ +export type Playlist = PlaylistMetadata & { + entities: number; + followers: number; + isFollowing: boolean; +}; diff --git a/plugins/playlist/.eslintrc.js b/plugins/playlist/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/playlist/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/playlist/README.md b/plugins/playlist/README.md new file mode 100644 index 0000000000..7c814d302b --- /dev/null +++ b/plugins/playlist/README.md @@ -0,0 +1,128 @@ +# Playlist Plugin + +Welcome to the playlist plugin! + +This plugin allows you to create, share, and follow custom collections of entities available in the Backstage catalog. + +## Setup + +Install this plugin: + +```bash +# From your Backstage root directory +yarn --cwd packages/app add @backstage/plugin-playlist +``` + +### Add the plugin to your `packages/app` + +Add the root page that the playlist plugin provides to your app. You can +choose any path for the route, but we recommend the following: + +```diff +// packages/app/src/App.tsx ++import { PlaylistIndexPage } from '@backstage/plugin-playlist'; + + + + } /> + }> + {entityPage} + ++ } /> + ... + +``` + +You may also want to add a link to the playlist page to your application sidebar: + +```diff +// packages/app/src/components/Root/Root.tsx ++import PlaylistPlayIcon from '@material-ui/icons/PlaylistPlay'; + +export const Root = ({ children }: PropsWithChildren<{}>) => ( + + ++ + ... + +``` + +### Entity Pages + +You can also make the following changes to add the playlist context menu to your `EntityPage.tsx` +to be able to add entities to playlists directly from your entity pages: + +First we need to add the following imports: + +```ts +import { EntityPlaylistDialog } from '@backstage/plugin-playlist'; +import PlaylistAddIcon from '@material-ui/icons/PlaylistAdd'; +``` + +Next we'll update the React import that looks like this: + +```ts +import React from 'react'; +``` + +To look like this: + +```ts +import React, { ReactNode, useMemo, useState } from 'react'; +``` + +Then we have to add this chunk of code after all the imports but before any of the other code: + +```ts +const EntityLayoutWrapper = (props: { children?: ReactNode }) => { + const [playlistDialogOpen, setPlaylistDialogOpen] = useState(false); + + const extraMenuItems = useMemo(() => { + return [ + { + title: 'Add to playlist', + Icon: PlaylistAddIcon, + onClick: () => setPlaylistDialogOpen(true), + }, + ]; + }, []); + + return ( + <> + + {props.children} + + setPlaylistDialogOpen(false)} + /> + + ); +}; +``` + +The last step is to wrap all the entity pages in the `EntityLayoutWrapper` like this: + +```diff +const defaultEntityPage = ( ++ + + {overviewContent} + + + + + + + + + ++ +); +``` + +Note: the above only shows an example for the `defaultEntityPage` for a full example of this you can look at [this EntityPage](../../packages/app/src/components/catalog/EntityPage.tsx) + +## Links + +- [playlist-backend](../playlist-backend) provides the backend API for this frontend. diff --git a/plugins/playlist/api-report.md b/plugins/playlist/api-report.md new file mode 100644 index 0000000000..ddfec2948d --- /dev/null +++ b/plugins/playlist/api-report.md @@ -0,0 +1,106 @@ +## API Report File for "@backstage/plugin-playlist" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiRef } from '@backstage/core-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; +import { RouteRef } from '@backstage/core-plugin-api'; + +// @public (undocumented) +export const EntityPlaylistDialog: ({ + open, + onClose, +}: EntityPlaylistDialogProps) => JSX.Element; + +// @public (undocumented) +export type EntityPlaylistDialogProps = { + open: boolean; + onClose: () => void; +}; + +// @public (undocumented) +export interface GetAllPlaylistsRequest { + // (undocumented) + editable?: boolean; + filter?: + | Record[] + | Record; +} + +// @public (undocumented) +export interface PlaylistApi { + // (undocumented) + addPlaylistEntities(playlistId: string, entityRefs: string[]): Promise; + // (undocumented) + createPlaylist(playlist: Omit): Promise; + // (undocumented) + deletePlaylist(playlistId: string): Promise; + // (undocumented) + followPlaylist(playlistId: string): Promise; + // (undocumented) + getAllPlaylists(req: GetAllPlaylistsRequest): Promise; + // (undocumented) + getPlaylist(playlistId: string): Promise; + // (undocumented) + getPlaylistEntities(playlistId: string): Promise; + // (undocumented) + removePlaylistEntities( + playlistId: string, + entityRefs: string[], + ): Promise; + // (undocumented) + unfollowPlaylist(playlistId: string): Promise; + // (undocumented) + updatePlaylist(playlist: PlaylistMetadata): Promise; +} + +// @public (undocumented) +export const playlistApiRef: ApiRef; + +// @public (undocumented) +export class PlaylistClient implements PlaylistApi { + constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }); + // (undocumented) + addPlaylistEntities(playlistId: string, entityRefs: string[]): Promise; + // (undocumented) + createPlaylist(playlist: Omit): Promise; + // (undocumented) + deletePlaylist(playlistId: string): Promise; + // (undocumented) + followPlaylist(playlistId: string): Promise; + // (undocumented) + getAllPlaylists(req?: GetAllPlaylistsRequest): Promise; + // (undocumented) + getPlaylist(playlistId: string): Promise; + // (undocumented) + getPlaylistEntities(playlistId: string): Promise; + // (undocumented) + removePlaylistEntities( + playlistId: string, + entityRefs: string[], + ): Promise; + // (undocumented) + unfollowPlaylist(playlistId: string): Promise; + // (undocumented) + updatePlaylist(playlist: PlaylistMetadata): Promise; +} + +// @public (undocumented) +export const PlaylistIndexPage: () => JSX.Element; + +// @public (undocumented) +export const playlistPlugin: BackstagePlugin< + { + root: RouteRef; + }, + {}, + {} +>; +``` diff --git a/packages/core-components/src/layout/HeaderActionMenu/VerticalMenuIcon.tsx b/plugins/playlist/dev/index.tsx similarity index 58% rename from packages/core-components/src/layout/HeaderActionMenu/VerticalMenuIcon.tsx rename to plugins/playlist/dev/index.tsx index a6a1d3a3d7..c9c626ab38 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/VerticalMenuIcon.tsx +++ b/plugins/playlist/dev/index.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * 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. @@ -13,13 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import React from 'react'; -import SvgIcon, { SvgIconProps } from '@material-ui/core/SvgIcon'; +import { createDevApp } from '@backstage/dev-utils'; +import { playlistPlugin, PlaylistIndexPage } from '../src/plugin'; -export const VerticalMenuIcon = (props: SvgIconProps) => - React.createElement( - SvgIcon, - props, - , - ); +createDevApp() + .registerPlugin(playlistPlugin) + .addPage({ + element: , + title: 'Root Page', + path: '/playlist', + }) + .render(); diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json new file mode 100644 index 0000000000..51cffcca9f --- /dev/null +++ b/plugins/playlist/package.json @@ -0,0 +1,67 @@ +{ + "name": "@backstage/plugin-playlist", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "frontend-plugin" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/catalog-model": "^1.1.0", + "@backstage/core-components": "^0.11.1-next.2", + "@backstage/core-plugin-api": "^1.0.6-next.2", + "@backstage/errors": "^1.1.0", + "@backstage/plugin-catalog-common": "^1.0.6-next.0", + "@backstage/plugin-catalog-react": "^1.1.4-next.1", + "@backstage/plugin-permission-common": "^0.6.4-next.1", + "@backstage/plugin-permission-react": "^0.4.5-next.1", + "@backstage/plugin-playlist-common": "^0.0.0", + "@backstage/plugin-search-react": "^1.1.0-next.2", + "@backstage/theme": "^0.2.16", + "@material-ui/core": "^4.9.13", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "^4.0.0-alpha.57", + "lodash": "^4.17.21", + "qs": "^6.9.4", + "react-hook-form": "^7.13.0", + "react-use": "^17.2.4" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0", + "react-router": "6.0.0-beta.0 || ^6.3.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + }, + "devDependencies": { + "@backstage/cli": "^0.19.0-next.2", + "@backstage/core-app-api": "^1.1.0-next.2", + "@backstage/dev-utils": "^1.0.6-next.1", + "@backstage/test-utils": "^1.2.0-next.2", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/react-hooks": "^8.0.0", + "@testing-library/user-event": "^14.0.0", + "@types/jest": "*", + "@types/node": "*", + "cross-fetch": "^3.1.5", + "msw": "^0.47.0", + "swr": "^1.1.2" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/playlist/src/api/PlaylistApi.ts b/plugins/playlist/src/api/PlaylistApi.ts new file mode 100644 index 0000000000..d0b87ec28a --- /dev/null +++ b/plugins/playlist/src/api/PlaylistApi.ts @@ -0,0 +1,75 @@ +/* + * 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 { createApiRef } from '@backstage/core-plugin-api'; +import { Playlist, PlaylistMetadata } from '@backstage/plugin-playlist-common'; + +/** + * @public + */ +export const playlistApiRef = createApiRef({ + id: 'plugin.playlist.service', +}); + +/** + * @public + */ +export interface GetAllPlaylistsRequest { + /** + * If multiple filter sets are given as an array, then there is effectively an + * OR between each filter set. + * + * Within one filter set, there is effectively an AND between the various + * keys. + * + * Within one key, if there are more than one value, then there is effectively + * an OR between them. + */ + filter?: + | Record[] + | Record; + + // If true, will filter results that satisfies the playlist.list.update permission + editable?: boolean; +} + +/** + * @public + */ +export interface PlaylistApi { + getAllPlaylists(req: GetAllPlaylistsRequest): Promise; + + createPlaylist(playlist: Omit): Promise; + + getPlaylist(playlistId: string): Promise; + + updatePlaylist(playlist: PlaylistMetadata): Promise; + + deletePlaylist(playlistId: string): Promise; + + addPlaylistEntities(playlistId: string, entityRefs: string[]): Promise; + + getPlaylistEntities(playlistId: string): Promise; + + removePlaylistEntities( + playlistId: string, + entityRefs: string[], + ): Promise; + + followPlaylist(playlistId: string): Promise; + + unfollowPlaylist(playlistId: string): Promise; +} diff --git a/plugins/playlist/src/api/PlaylistClient.test.ts b/plugins/playlist/src/api/PlaylistClient.test.ts new file mode 100644 index 0000000000..f3b62c19ac --- /dev/null +++ b/plugins/playlist/src/api/PlaylistClient.test.ts @@ -0,0 +1,272 @@ +/* + * 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 { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; + +import { PlaylistClient } from './PlaylistClient'; + +const server = setupServer(); + +describe('PlaylistClient', () => { + setupRequestMockHandlers(server); + const mockBaseUrl = 'http://backstage/api/playlist'; + const discoveryApi = { getBaseUrl: async () => mockBaseUrl }; + const fetchApi = new MockFetchApi(); + + let client: PlaylistClient; + beforeEach(() => { + client = new PlaylistClient({ discoveryApi, fetchApi }); + }); + + describe('getAllPlaylists', () => { + const expectedResp = [ + { + id: 'id', + name: 'name', + description: 'description', + owner: 'owner', + public: true, + entities: 1, + followers: 2, + isFollowing: true, + }, + ]; + + it('should fetch playlists from correct endpoint', async () => { + server.use( + rest.get(`${mockBaseUrl}/`, (_, res, ctx) => + res(ctx.json(expectedResp)), + ), + ); + const response = await client.getAllPlaylists(); + expect(response).toEqual(expectedResp); + }); + + it('should fetch editable playlists correctly', async () => { + expect.assertions(2); + + server.use( + rest.get(`${mockBaseUrl}/`, (req, res, ctx) => { + expect(req.url.search).toBe('?editable=true'); + return res(ctx.json(expectedResp)); + }), + ); + + const response = await client.getAllPlaylists({ editable: true }); + expect(response).toEqual(expectedResp); + }); + + it('builds multiple search filters properly', async () => { + expect.assertions(2); + + server.use( + rest.get(`${mockBaseUrl}/`, (req, res, ctx) => { + expect(req.url.search).toBe( + '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2&editable=true', + ); + return res(ctx.json(expectedResp)); + }), + ); + + const response = await client.getAllPlaylists({ + editable: true, + filter: [ + { + a: '1', + b: ['2', '3'], + ö: '=', + }, + { + a: '2', + }, + ], + }); + + expect(response).toEqual(expectedResp); + }); + + it('builds single search filter properly', async () => { + expect.assertions(2); + + server.use( + rest.get(`${mockBaseUrl}/`, (req, res, ctx) => { + expect(req.url.search).toBe('?filter=a=1,b=2,b=3,%C3%B6=%3D'); + return res(ctx.json(expectedResp)); + }), + ); + + const response = await client.getAllPlaylists({ + filter: { + a: '1', + b: ['2', '3'], + ö: '=', + }, + }); + + expect(response).toEqual(expectedResp); + }); + }); + + it('createPlaylist', async () => { + expect.assertions(2); + + const newPlaylist = { + name: 'name', + description: 'description', + owner: 'owner', + public: true, + }; + + server.use( + rest.post(`${mockBaseUrl}/`, (req, res, ctx) => { + expect(req.body).toEqual(newPlaylist); + return res(ctx.json('123')); + }), + ); + + const response = await client.createPlaylist(newPlaylist); + + expect(response).toEqual('123'); + }); + + it('getPlaylist', async () => { + const playlist = { + id: '123', + name: 'name', + description: 'description', + owner: 'owner', + public: true, + entities: 1, + followers: 2, + isFollowing: true, + }; + + server.use( + rest.get(`${mockBaseUrl}/123`, (_, res, ctx) => res(ctx.json(playlist))), + ); + + const response = await client.getPlaylist('123'); + expect(response).toEqual(playlist); + }); + + it('updatePlaylist', async () => { + expect.assertions(1); + + const playlist = { + id: 'id', + name: 'name', + description: 'description', + owner: 'owner', + public: true, + }; + + server.use( + rest.put(`${mockBaseUrl}/id`, (req, res) => { + expect(req.body).toEqual(playlist); + return res(); + }), + ); + + await client.updatePlaylist(playlist); + }); + + it('deletePlaylist', async () => { + expect.assertions(1); + + server.use( + rest.delete(`${mockBaseUrl}/id`, (_, res) => { + // eslint requires at least 1 assertion so this is here is verify this handler is called + expect(true).toBe(true); + return res(); + }), + ); + + await client.deletePlaylist('id'); + }); + + it('addPlaylistEntities', async () => { + expect.assertions(1); + + const entities = ['component:default/ent1', 'component:default/ent2']; + + server.use( + rest.post(`${mockBaseUrl}/id/entities`, (req, res) => { + expect(req.body).toEqual(entities); + return res(); + }), + ); + + await client.addPlaylistEntities('id', entities); + }); + + it('getPlaylistEntities', async () => { + const entities = ['component:default/ent1', 'component:default/ent2']; + + server.use( + rest.get(`${mockBaseUrl}/id/entities`, (_, res, ctx) => + res(ctx.json(entities)), + ), + ); + + const response = await client.getPlaylistEntities('id'); + expect(response).toEqual(entities); + }); + + it('removePlaylistEntities', async () => { + expect.assertions(1); + + const entities = ['component:default/ent1', 'component:default/ent2']; + + server.use( + rest.delete(`${mockBaseUrl}/id/entities`, (req, res) => { + expect(req.body).toEqual(entities); + return res(); + }), + ); + + await client.removePlaylistEntities('id', entities); + }); + + it('followPlaylist', async () => { + expect.assertions(1); + + server.use( + rest.post(`${mockBaseUrl}/id/followers`, (_, res) => { + // eslint requires at least 1 assertion so this is here is verify this handler is called + expect(true).toBe(true); + return res(); + }), + ); + + await client.followPlaylist('id'); + }); + + it('unfollowPlaylist', async () => { + expect.assertions(1); + + server.use( + rest.delete(`${mockBaseUrl}/id/followers`, (_, res) => { + // eslint requires at least 1 assertion so this is here is verify this handler is called + expect(true).toBe(true); + return res(); + }), + ); + + await client.unfollowPlaylist('id'); + }); +}); diff --git a/plugins/playlist/src/api/PlaylistClient.ts b/plugins/playlist/src/api/PlaylistClient.ts new file mode 100644 index 0000000000..b77aa79733 --- /dev/null +++ b/plugins/playlist/src/api/PlaylistClient.ts @@ -0,0 +1,198 @@ +/* + * 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 { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { Playlist, PlaylistMetadata } from '@backstage/plugin-playlist-common'; + +import { GetAllPlaylistsRequest, PlaylistApi } from './PlaylistApi'; + +/** + * @public + */ +export class PlaylistClient implements PlaylistApi { + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi; + } + + async getAllPlaylists(req: GetAllPlaylistsRequest = {}): Promise { + const { filter = [], editable } = req; + const params: string[] = []; + + // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters + // the "inner array" defined within a `filter` param corresponds to "allOf" filters + for (const filterItem of [filter].flat()) { + const filterParts: string[] = []; + for (const [key, value] of Object.entries(filterItem)) { + for (const v of [value].flat()) { + if (typeof v === 'string') { + filterParts.push( + `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, + ); + } + } + } + + if (filterParts.length) { + params.push(`filter=${filterParts.join(',')}`); + } + } + + if (editable) { + params.push('editable=true'); + } + + const query = params.length ? `?${params.join('&')}` : ''; + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch(`${baseUrl}/${query}`, { + method: 'GET', + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return await resp.json(); + } + + async createPlaylist( + playlist: Omit, + ): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch(`${baseUrl}/`, { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify(playlist), + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return await resp.json(); + } + + async getPlaylist(playlistId: string): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch(`${baseUrl}/${playlistId}`, { + method: 'GET', + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return await resp.json(); + } + + async updatePlaylist(playlist: PlaylistMetadata) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch(`${baseUrl}/${playlist.id}`, { + headers: { 'Content-Type': 'application/json' }, + method: 'PUT', + body: JSON.stringify(playlist), + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async deletePlaylist(playlistId: string) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch(`${baseUrl}/${playlistId}`, { + method: 'DELETE', + }); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async addPlaylistEntities(playlistId: string, entityRefs: string[]) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/${playlistId}/entities`, + { + headers: { 'Content-Type': 'application/json' }, + method: 'POST', + body: JSON.stringify(entityRefs), + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async getPlaylistEntities(playlistId: string): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/${playlistId}/entities`, + { method: 'GET' }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + + return await resp.json(); + } + + async removePlaylistEntities(playlistId: string, entityRefs: string[]) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/${playlistId}/entities`, + { + headers: { 'Content-Type': 'application/json' }, + method: 'DELETE', + body: JSON.stringify(entityRefs), + }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async followPlaylist(playlistId: string) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/${playlistId}/followers`, + { method: 'POST' }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } + + async unfollowPlaylist(playlistId: string) { + const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); + const resp = await this.fetchApi.fetch( + `${baseUrl}/${playlistId}/followers`, + { method: 'DELETE' }, + ); + + if (!resp.ok) { + throw await ResponseError.fromResponse(resp); + } + } +} diff --git a/plugins/playlist/src/api/index.ts b/plugins/playlist/src/api/index.ts new file mode 100644 index 0000000000..b53cbd99ef --- /dev/null +++ b/plugins/playlist/src/api/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './PlaylistClient'; +export * from './PlaylistApi'; diff --git a/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx new file mode 100644 index 0000000000..e00f7dc582 --- /dev/null +++ b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx @@ -0,0 +1,142 @@ +/* + * 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 { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + PermissionApi, + permissionApiRef, +} from '@backstage/plugin-permission-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { Button } from '@material-ui/core'; +import { fireEvent, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; +import { SWRConfig } from 'swr'; + +import { PlaylistApi, playlistApiRef } from '../../api'; +import { rootRouteRef } from '../../routes'; +import { CreatePlaylistButton } from './CreatePlaylistButton'; + +jest.mock('../PlaylistEditDialog', () => ({ + PlaylistEditDialog: ({ onSave, open }: { onSave: Function; open: boolean }) => + open ? ( + + )} + setOpenDialog(false)} + onSave={savePlaylist} + /> + + ); +}; diff --git a/plugins/playlist/src/components/CreatePlaylistButton/index.ts b/plugins/playlist/src/components/CreatePlaylistButton/index.ts new file mode 100644 index 0000000000..ac28bbc509 --- /dev/null +++ b/plugins/playlist/src/components/CreatePlaylistButton/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 * from './CreatePlaylistButton'; diff --git a/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx new file mode 100644 index 0000000000..9c61105ef9 --- /dev/null +++ b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx @@ -0,0 +1,200 @@ +/* + * 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 { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + PermissionApi, + permissionApiRef, +} from '@backstage/plugin-permission-react'; +import { Button } from '@material-ui/core'; +import { fireEvent, getByRole, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; +import { SWRConfig } from 'swr'; + +import { PlaylistApi, playlistApiRef } from '../../api'; +import { rootRouteRef } from '../../routes'; +import { EntityPlaylistDialog } from './EntityPlaylistDialog'; + +const navigateMock = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => navigateMock, +})); + +jest.mock('../PlaylistEditDialog', () => ({ + PlaylistEditDialog: ({ onSave, open }: { onSave: Function; open: boolean }) => + open ? ( + + + + setOpenEditDialog(false)} + onSave={createNewPlaylist} + /> + + ); +}; diff --git a/plugins/playlist/src/components/EntityPlaylistDialog/index.ts b/plugins/playlist/src/components/EntityPlaylistDialog/index.ts new file mode 100644 index 0000000000..77d7e73ae0 --- /dev/null +++ b/plugins/playlist/src/components/EntityPlaylistDialog/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 * from './EntityPlaylistDialog'; diff --git a/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.test.tsx b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.test.tsx new file mode 100644 index 0000000000..9255ee1bdb --- /dev/null +++ b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.test.tsx @@ -0,0 +1,286 @@ +/* + * 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 { ApiProvider } from '@backstage/core-app-api'; +import { + ConfigApi, + configApiRef, + IdentityApi, + identityApiRef, + storageApiRef, +} from '@backstage/core-plugin-api'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { MockStorageApi, TestApiRegistry } from '@backstage/test-utils'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import React from 'react'; + +import { MockPlaylistListProvider } from '../../testUtils'; +import { PlaylistOwnerFilter } from '../PlaylistOwnerPicker'; +import { PersonalListPicker } from './PersonalListPicker'; + +const mockConfigApi = { + getOptionalString: () => 'Test Company', +} as Partial; + +const mockIdentityApi = { + getBackstageIdentity: async () => ({ + ownershipEntityRefs: ['user:default/owner', 'group:default/some-owner'], + }), +} as Partial; + +const apis = TestApiRegistry.from( + [configApiRef, mockConfigApi], + [identityApiRef, mockIdentityApi], + [storageApiRef, MockStorageApi.create()], +); + +const backendPlaylists: Playlist[] = [ + { + id: 'id1', + name: 'playlist-1', + owner: 'group:default/some-owner', + public: true, + entities: 1, + followers: 2, + isFollowing: false, + }, + { + id: 'id2', + name: 'playlist-2', + owner: 'group:default/another-owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, + { + id: 'id3', + name: 'playlist-3', + owner: 'group:default/another-owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, + { + id: 'id4', + name: 'playlist-4', + owner: 'user:default/owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, +]; + +describe('', () => { + const updateFilters = jest.fn() as any; + + beforeEach(() => { + updateFilters.mockClear(); + }); + + it('renders filter groups', async () => { + const { queryByText } = render( + + + + + , + ); + + await waitFor(() => { + expect(queryByText('Personal')).toBeInTheDocument(); + expect(queryByText('Test Company')).toBeInTheDocument(); + }); + }); + + it('renders filters', async () => { + const { getAllByRole } = render( + + + + + , + ); + + await waitFor(() => { + expect( + getAllByRole('menuitem').map(({ textContent }) => textContent), + ).toEqual(['Owned 2', 'Following 3', 'All 4']); + }); + }); + + it('respects other frontend filters in counts', async () => { + const { getAllByRole } = render( + + + + + , + ); + + await waitFor(() => { + expect( + getAllByRole('menuitem').map(({ textContent }) => textContent), + ).toEqual(['Owned -', 'Following 2', 'All 2']); + }); + }); + + it('respects the query parameter filter value', async () => { + const queryParameters = { personal: 'owned' }; + render( + + + + + , + ); + + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe('owned'); + }); + }); + + it('updates personal filter when a menuitem is selected', async () => { + const { getByText } = render( + + + + + , + ); + + fireEvent.click(getByText('Following')); + + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe('following'); + }); + }); + + it('responds to external queryParameters changes', async () => { + const rendered = render( + + + + + , + ); + + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe('all'); + }); + + rendered.rerender( + + + + + , + ); + + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe('owned'); + }); + }); + + describe.each(['owned', 'following'])( + 'filter resetting for %s playlists', + type => { + const picker = (props: { loading: boolean; mockData: any }) => ( + + ({ + ...p, + ...props.mockData, + })), + queryParameters: { personal: type }, + updateFilters, + loading: props.loading, + }} + > + + + + ); + + describe(`when there are no ${type} playlists`, () => { + const mockData = + type === 'owned' + ? { owner: 'group:default/no-owner' } + : { isFollowing: false }; + + it('does not reset the filter while playlists are loading', async () => { + render(picker({ loading: true, mockData })); + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).not.toBe( + 'all', + ); + }); + }); + + it('resets the filter to "all" when playlists are loaded', async () => { + render(picker({ loading: false, mockData })); + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe('all'); + }); + }); + }); + + describe(`when there are some ${type} playlists present`, () => { + const mockData = {}; + + it('does not reset the filter while playlists are loading', async () => { + render(picker({ loading: true, mockData })); + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).not.toBe( + 'all', + ); + }); + }); + + it('does not reset the filter when playlists are loaded', async () => { + render(picker({ loading: false, mockData })); + await waitFor(() => { + expect(updateFilters.mock.lastCall[0].personal.value).toBe(type); + }); + }); + }); + }, + ); +}); diff --git a/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx new file mode 100644 index 0000000000..1172f2f6fa --- /dev/null +++ b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx @@ -0,0 +1,293 @@ +/* + * 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 { + configApiRef, + IconComponent, + identityApiRef, + useApi, +} from '@backstage/core-plugin-api'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { + Card, + List, + ListItemIcon, + ListItemSecondaryAction, + ListItemText, + makeStyles, + MenuItem, + Theme, + Typography, +} from '@material-ui/core'; +import PlaylistPlayIcon from '@material-ui/icons/PlaylistPlay'; +import SettingsIcon from '@material-ui/icons/Settings'; +import { compact } from 'lodash'; +import React, { Fragment, useEffect, useMemo, useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; + +import { usePlaylistList } from '../../hooks'; +import { PlaylistFilter } from '../../types'; + +export const enum PersonalListFilterValue { + owned = 'owned', + following = 'following', + all = 'all', +} + +export class PersonalListFilter implements PlaylistFilter { + constructor( + readonly value: PersonalListFilterValue, + readonly isOwnedPlaylist: (playlist: Playlist) => boolean, + ) {} + + filterPlaylist(playlist: Playlist): boolean { + switch (this.value) { + case PersonalListFilterValue.owned: + return this.isOwnedPlaylist(playlist); + case PersonalListFilterValue.following: + return playlist.isFollowing; + default: + return true; + } + } + + toQueryValue(): string { + return this.value; + } +} + +const useStyles = makeStyles(theme => ({ + root: { + backgroundColor: 'rgba(0, 0, 0, .11)', + boxShadow: 'none', + margin: theme.spacing(1, 0, 1, 0), + }, + title: { + margin: theme.spacing(1, 0, 0, 1), + textTransform: 'uppercase', + fontSize: 12, + fontWeight: 'bold', + }, + listIcon: { + minWidth: 30, + color: theme.palette.text.primary, + }, + menuItem: { + minHeight: theme.spacing(6), + }, + groupWrapper: { + margin: theme.spacing(1, 1, 2, 1), + }, +})); + +type ButtonGroup = { + name: string; + items: { + id: PersonalListFilterValue; + label: string; + icon?: IconComponent; + }[]; +}; + +function getFilterGroups(orgName: string | undefined): ButtonGroup[] { + return [ + { + name: 'Personal', + items: [ + { + id: PersonalListFilterValue.owned, + label: 'Owned', + icon: SettingsIcon, + }, + { + id: PersonalListFilterValue.following, + label: 'Following', + icon: PlaylistPlayIcon, + }, + ], + }, + { + name: orgName ?? 'Company', + items: [ + { + id: PersonalListFilterValue.all, + label: 'All', + }, + ], + }, + ]; +} + +export const PersonalListPicker = () => { + const classes = useStyles(); + const configApi = useApi(configApiRef); + const identityApi = useApi(identityApiRef); + const orgName = configApi.getOptionalString('organization.name') ?? 'Company'; + const filterGroups = getFilterGroups(orgName); + + const { loading: loadingOwnership, value: ownershipRefs } = + useAsync(async () => { + const { ownershipEntityRefs } = await identityApi.getBackstageIdentity(); + return ownershipEntityRefs; + }, []); + + const isOwnedPlaylist = useMemo(() => { + const myOwnerRefs = new Set(ownershipRefs ?? []); + return (playlist: Playlist) => myOwnerRefs.has(playlist.owner); + }, [ownershipRefs]); + + const { + filters, + updateFilters, + backendPlaylists, + queryParameters: { personal: personalParameter }, + loading: loadingBackendPlaylists, + } = usePlaylistList(); + + const loading = loadingBackendPlaylists || loadingOwnership; + + // Static filters; used for generating counts of potentially unselected options + const ownedFilter = useMemo( + () => + new PersonalListFilter(PersonalListFilterValue.owned, isOwnedPlaylist), + [isOwnedPlaylist], + ); + const followingFilter = useMemo( + () => + new PersonalListFilter( + PersonalListFilterValue.following, + isOwnedPlaylist, + ), + [isOwnedPlaylist], + ); + + const queryParamPersonalFilter = useMemo( + () => [personalParameter].flat()[0], + [personalParameter], + ); + + const [selectedPersonalFilter, setSelectedPersonalFilter] = useState( + queryParamPersonalFilter ?? PersonalListFilterValue.all, + ); + + // To show proper counts for each section, apply all other frontend filters _except_ the personal + // filter that's controlled by this picker. + const playlistsWithoutPersonalFilter = useMemo( + () => + backendPlaylists.filter(playlist => + compact(Object.values({ ...filters, personal: undefined })).every( + (filter: PlaylistFilter) => + !filter.filterPlaylist || filter.filterPlaylist(playlist), + ), + ), + [filters, backendPlaylists], + ); + + const filterCounts = useMemo>( + () => ({ + all: playlistsWithoutPersonalFilter.length, + following: playlistsWithoutPersonalFilter.filter(playlist => + followingFilter.filterPlaylist(playlist), + ).length, + owned: playlistsWithoutPersonalFilter.filter(playlist => + ownedFilter.filterPlaylist(playlist), + ).length, + }), + [playlistsWithoutPersonalFilter, followingFilter, ownedFilter], + ); + + // Set selected personal filter on query parameter updates; this happens at initial page load and from + // external updates to the page location. + useEffect(() => { + if (queryParamPersonalFilter) { + setSelectedPersonalFilter(queryParamPersonalFilter); + } + }, [queryParamPersonalFilter]); + + useEffect(() => { + if ( + !loading && + !!selectedPersonalFilter && + selectedPersonalFilter !== PersonalListFilterValue.all && + filterCounts[selectedPersonalFilter] === 0 + ) { + setSelectedPersonalFilter(PersonalListFilterValue.all); + } + }, [ + loading, + filterCounts, + selectedPersonalFilter, + setSelectedPersonalFilter, + ]); + + useEffect(() => { + updateFilters({ + personal: selectedPersonalFilter + ? new PersonalListFilter( + selectedPersonalFilter as PersonalListFilterValue, + isOwnedPlaylist, + ) + : undefined, + }); + }, [selectedPersonalFilter, isOwnedPlaylist, updateFilters]); + + return ( + + {filterGroups.map(group => ( + + + {group.name} + + + + {group.items.map(item => ( + setSelectedPersonalFilter(item.id)} + selected={item.id === selectedPersonalFilter} + className={classes.menuItem} + disabled={filterCounts[item.id] === 0} + data-testid={`personal-picker-${item.id}`} + tabIndex={0} + ContainerProps={{ role: 'menuitem' }} + > + {item.icon && ( + + + + )} + + {item.label} + + + {filterCounts[item.id] || '-'} + + + ))} + + + + ))} + + ); +}; diff --git a/plugins/playlist/src/components/PersonalListPicker/index.ts b/plugins/playlist/src/components/PersonalListPicker/index.ts new file mode 100644 index 0000000000..f67f18ab39 --- /dev/null +++ b/plugins/playlist/src/components/PersonalListPicker/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 * from './PersonalListPicker'; diff --git a/plugins/playlist/src/components/PlaylistCard/PlaylistCard.test.tsx b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.test.tsx new file mode 100644 index 0000000000..177cc23b81 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.test.tsx @@ -0,0 +1,57 @@ +/* + * 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 { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { lightTheme } from '@backstage/theme'; +import { ThemeProvider } from '@material-ui/core'; +import React from 'react'; + +import { rootRouteRef } from '../../routes'; +import { PlaylistCard } from './PlaylistCard'; + +describe('', () => { + it('renders playlist info', async () => { + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/playlists': rootRouteRef, + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + expect(rendered.getByText('playlist-1')).toBeInTheDocument(); + expect(rendered.getByText('test description')).toBeInTheDocument(); + expect(rendered.getByText('some-owner')).toBeInTheDocument(); + expect(rendered.getByText('3 entities')).toBeInTheDocument(); + expect(rendered.getByText('2 followers')).toBeInTheDocument(); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx new file mode 100644 index 0000000000..2db7e85f7e --- /dev/null +++ b/plugins/playlist/src/components/PlaylistCard/PlaylistCard.tsx @@ -0,0 +1,131 @@ +/* + * 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 { + Button, + ItemCardHeader, + MarkdownContent, +} from '@backstage/core-components'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import { EntityRefLinks } from '@backstage/plugin-catalog-react'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { BackstageTheme } from '@backstage/theme'; +import { + Box, + Card, + CardActions, + CardContent, + CardMedia, + Chip, + makeStyles, + Tooltip, + Typography, +} from '@material-ui/core'; +import LockIcon from '@material-ui/icons/Lock'; +import React from 'react'; + +import { playlistRouteRef } from '../../routes'; + +const useStyles = makeStyles((theme: BackstageTheme) => ({ + cardHeader: { + position: 'relative', + }, + title: { + backgroundImage: theme.getPageTheme({ themeId: 'home' }).backgroundImage, + }, + box: { + overflow: 'hidden', + textOverflow: 'ellipsis', + display: '-webkit-box', + '-webkit-line-clamp': 10, + '-webkit-box-orient': 'vertical', + paddingBottom: '0.8em', + }, + label: { + color: theme.palette.text.secondary, + textTransform: 'uppercase', + fontSize: '0.65rem', + fontWeight: 'bold', + letterSpacing: 0.5, + lineHeight: 1, + paddingBottom: '0.2rem', + }, + chip: { + marginRight: 'auto', + }, + privateIcon: { + position: 'absolute', + top: theme.spacing(0.5), + right: theme.spacing(0.5), + padding: '0.25rem', + }, +})); + +export type PlaylistCardProps = { + playlist: Playlist; +}; + +export const PlaylistCard = ({ playlist }: PlaylistCardProps) => { + const classes = useStyles(); + const playlistRoute = useRouteRef(playlistRouteRef); + + return ( + + + {!playlist.public && ( + + + + )} + + + + + + + + + Description + + + + + + Owner + + + + + + + + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistCard/index.ts b/plugins/playlist/src/components/PlaylistCard/index.ts new file mode 100644 index 0000000000..d043c8b6d0 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistCard/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 * from './PlaylistCard'; diff --git a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx new file mode 100644 index 0000000000..9f30d7608c --- /dev/null +++ b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx @@ -0,0 +1,86 @@ +/* + * 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 { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { fireEvent, getByRole, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; + +import { PlaylistEditDialog } from './PlaylistEditDialog'; + +describe('', () => { + it('handle saving with an edited playlist', async () => { + const identityApi: Partial = { + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/me', + ownershipEntityRefs: ['group:default/test-owner', 'user:default/me'], + }), + }; + + const mockOnSave = jest.fn().mockImplementation(async () => {}); + const rendered = await renderInTestApp( + + + , + ); + + act(() => { + fireEvent.input( + getByRole(rendered.getByTestId('edit-dialog-name-input'), 'textbox'), + { + target: { + value: 'test playlist', + }, + }, + ); + + fireEvent.input( + getByRole( + rendered.getByTestId('edit-dialog-description-input'), + 'textbox', + ), + { + target: { + value: 'test description', + }, + }, + ); + + fireEvent.mouseDown( + getByRole(rendered.getByTestId('edit-dialog-owner-select'), 'button'), + ); + + fireEvent.click(rendered.getByText('test-owner')); + + fireEvent.click( + getByRole(rendered.getByTestId('edit-dialog-public-option'), 'radio'), + ); + + fireEvent.click(rendered.getByTestId('edit-dialog-save-button')); + }); + + await waitFor(() => { + expect(mockOnSave).toHaveBeenCalledWith({ + name: 'test playlist', + description: 'test description', + owner: 'group:default/test-owner', + public: true, + }); + }); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.tsx b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.tsx new file mode 100644 index 0000000000..27cc13fede --- /dev/null +++ b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.tsx @@ -0,0 +1,217 @@ +/* + * 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 { parseEntityRef } from '@backstage/catalog-model'; +import { identityApiRef, useApi } from '@backstage/core-plugin-api'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; +import { + Button, + CircularProgress, + Dialog, + DialogActions, + DialogContent, + FormControl, + FormControlLabel, + InputLabel, + makeStyles, + MenuItem, + LinearProgress, + Radio, + RadioGroup, + Select, + TextField, +} from '@material-ui/core'; +import React from 'react'; +import { useForm, Controller } from 'react-hook-form'; +import useAsync from 'react-use/lib/useAsync'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +const useStyles = makeStyles({ + buttonWrapper: { + position: 'relative', + }, + buttonProgress: { + position: 'absolute', + top: '50%', + left: '50%', + marginTop: -12, + marginLeft: -12, + }, +}); + +export type PlaylistEditDialogProps = { + open: boolean; + onClose: () => void; + onSave: (playlist: Omit) => Promise; + playlist?: Omit; +}; + +export const PlaylistEditDialog = ({ + open, + onClose, + onSave, + playlist = { + name: '', + description: '', + owner: '', + public: false, + }, +}: PlaylistEditDialogProps) => { + const classes = useStyles(); + const identityApi = useApi(identityApiRef); + + const { loading: loadingOwnership, value: ownershipRefs } = + useAsync(async () => { + const { ownershipEntityRefs } = await identityApi.getBackstageIdentity(); + return ownershipEntityRefs; + }, []); + + const defaultValues = { + ...playlist, + public: playlist.public.toString(), + }; + + const { + control, + formState: { errors }, + handleSubmit, + reset, + } = useForm({ defaultValues }); + + const [saving, savePlaylist] = useAsyncFn( + formValues => + onSave({ ...formValues, public: JSON.parse(formValues.public) }), + [onSave], + ); + + const closeDialog = () => { + if (!saving.loading) { + onClose(); + reset(defaultValues); + } + }; + + return ( + + + ( + + )} + /> + ( + + )} + /> + {loadingOwnership ? ( + + ) : ( + ( + + Owner + + + )} + /> + )} + ( + + + } + /> + } + /> + + + )} + /> + + + +
+ + {saving.loading && ( + + )} +
+
+
+ ); +}; diff --git a/plugins/playlist/src/components/PlaylistEditDialog/index.ts b/plugins/playlist/src/components/PlaylistEditDialog/index.ts new file mode 100644 index 0000000000..3355443b82 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistEditDialog/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 * from './PlaylistEditDialog'; diff --git a/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.test.tsx b/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.test.tsx new file mode 100644 index 0000000000..6dae17d3bc --- /dev/null +++ b/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + PermissionApi, + permissionApiRef, +} from '@backstage/plugin-permission-react'; +import React from 'react'; + +import { PlaylistApi, playlistApiRef } from '../../api'; +import { rootRouteRef } from '../../routes'; +import { PlaylistIndexPage } from './PlaylistIndexPage'; + +const playlistApi: Partial = { + getAllPlaylists: async () => [], +}; + +const permissionApi: Partial = { + authorize: async () => ({ result: AuthorizeResult.ALLOW }), +}; + +describe('PlaylistIndexPage', () => { + it('should render', async () => { + const rendered = await renderInTestApp( + + + , + { mountedRoutes: { '/playlists': rootRouteRef } }, + ); + expect(rendered.getByText('Playlists')).toBeInTheDocument(); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.tsx b/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.tsx new file mode 100644 index 0000000000..0ee829018a --- /dev/null +++ b/plugins/playlist/src/components/PlaylistIndexPage/PlaylistIndexPage.tsx @@ -0,0 +1,56 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { + PageWithHeader, + Content, + ContentHeader, + SupportButton, +} from '@backstage/core-components'; +import { CatalogFilterLayout } from '@backstage/plugin-catalog-react'; + +import { PlaylistListProvider } from '../../hooks'; +import { CreatePlaylistButton } from '../CreatePlaylistButton'; +import { PersonalListPicker } from '../PersonalListPicker'; +import { PlaylistList } from '../PlaylistList'; +import { PlaylistOwnerPicker } from '../PlaylistOwnerPicker'; +import { PlaylistSearchBar } from '../PlaylistSearchBar'; +import { PlaylistSortPicker } from '../PlaylistSortPicker'; + +export const PlaylistIndexPage = () => ( + + + + + + + + + + + + + + + + + + + + + +); diff --git a/plugins/playlist/src/components/PlaylistIndexPage/index.ts b/plugins/playlist/src/components/PlaylistIndexPage/index.ts new file mode 100644 index 0000000000..06858a8262 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistIndexPage/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { PlaylistIndexPage } from './PlaylistIndexPage'; diff --git a/plugins/playlist/src/components/PlaylistList/PlaylistList.test.tsx b/plugins/playlist/src/components/PlaylistList/PlaylistList.test.tsx new file mode 100644 index 0000000000..27030ec1c7 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistList/PlaylistList.test.tsx @@ -0,0 +1,86 @@ +/* + * 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 { Playlist } from '@backstage/plugin-playlist-common'; +import { render } from '@testing-library/react'; +import React from 'react'; + +import { MockPlaylistListProvider } from '../../testUtils'; +import { PlaylistList } from './PlaylistList'; + +jest.mock('../PlaylistCard', () => ({ + PlaylistCard: ({ playlist }: { playlist: Playlist }) => ( +
{playlist.name}
+ ), +})); + +describe('', () => { + it('renders error on error', () => { + const rendered = render( + + + , + ); + + expect(rendered.getByText('Test Error')).toBeInTheDocument(); + }); + + it('handles no playlists', () => { + const rendered = render( + + + , + ); + + expect( + rendered.getByText('No playlists found that match your filter.'), + ).toBeInTheDocument(); + }); + + it('renders playlists', () => { + const rendered = render( + + + , + ); + + expect(rendered.getByText('playlist-1')).toBeInTheDocument(); + expect(rendered.getByText('playlist-2')).toBeInTheDocument(); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistList/PlaylistList.tsx b/plugins/playlist/src/components/PlaylistList/PlaylistList.tsx new file mode 100644 index 0000000000..fcc3971542 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistList/PlaylistList.tsx @@ -0,0 +1,58 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { + Content, + ItemCardGrid, + Progress, + WarningPanel, +} from '@backstage/core-components'; +import { Typography } from '@material-ui/core'; + +import { usePlaylistList } from '../../hooks'; +import { PlaylistCard } from '../PlaylistCard'; + +export const PlaylistList = () => { + const { loading, error, playlists } = usePlaylistList(); + + return ( + <> + {loading && } + + {error && ( + + {error.message} + + )} + + {!error && !loading && !playlists.length && ( + + No playlists found that match your filter. + + )} + + + + {playlists?.length > 0 && + playlists.map(playlist => ( + + ))} + + + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistList/index.ts b/plugins/playlist/src/components/PlaylistList/index.ts new file mode 100644 index 0000000000..59fa5cf0fb --- /dev/null +++ b/plugins/playlist/src/components/PlaylistList/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 * from './PlaylistList'; diff --git a/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.test.tsx b/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.test.tsx new file mode 100644 index 0000000000..c74e6f6853 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.test.tsx @@ -0,0 +1,215 @@ +/* + * 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 { parseEntityRef } from '@backstage/catalog-model'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { MockPlaylistListProvider } from '../../testUtils'; +import { + PlaylistOwnerFilter, + PlaylistOwnerPicker, +} from './PlaylistOwnerPicker'; + +const samplePlaylists: Playlist[] = [ + { + id: 'id1', + name: 'playlist-1', + owner: 'group:default/some-owner', + public: true, + entities: 1, + followers: 2, + isFollowing: false, + }, + { + id: 'id2', + name: 'playlist-2', + owner: 'group:default/another-owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, + { + id: 'id3', + name: 'playlist-3', + owner: 'group:default/another-owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, + { + id: 'id4', + name: 'playlist-4', + owner: 'user:default/owner', + public: true, + entities: 2, + followers: 1, + isFollowing: true, + }, +]; + +describe('', () => { + it('renders all owners', () => { + const rendered = render( + + + , + ); + expect(rendered.getByText('Owner')).toBeInTheDocument(); + + fireEvent.click(rendered.getByTestId('owner-picker-expand')); + samplePlaylists + .map(p => + humanizeEntityRef(parseEntityRef(p.owner), { defaultKind: 'group' }), + ) + .forEach(owner => { + expect(rendered.getByText(owner as string)).toBeInTheDocument(); + }); + }); + + it('renders unique owners in alphabetical order', () => { + const rendered = render( + + + , + ); + expect(rendered.getByText('Owner')).toBeInTheDocument(); + + fireEvent.click(rendered.getByTestId('owner-picker-expand')); + + expect(rendered.getAllByRole('option').map(o => o.textContent)).toEqual([ + 'another-owner', + 'some-owner', + 'user:owner', + ]); + }); + + it('respects the query parameter filter value', () => { + const updateFilters = jest.fn(); + const queryParameters = { owners: ['group:default/another-owner'] }; + render( + + + , + ); + + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: new PlaylistOwnerFilter(['group:default/another-owner']), + }); + }); + + it('adds owners to filters', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: undefined, + }); + + fireEvent.click(rendered.getByTestId('owner-picker-expand')); + fireEvent.click(rendered.getByText('some-owner')); + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: new PlaylistOwnerFilter(['group:default/some-owner']), + }); + }); + + it('removes owners from filters', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: new PlaylistOwnerFilter(['group:default/some-owner']), + }); + fireEvent.click(rendered.getByTestId('owner-picker-expand')); + expect(rendered.getByLabelText('some-owner')).toBeChecked(); + + fireEvent.click(rendered.getByLabelText('some-owner')); + expect(updateFilters).toHaveBeenLastCalledWith({ + owner: undefined, + }); + }); + + it('responds to external queryParameters changes', () => { + const updateFilters = jest.fn(); + const rendered = render( + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: new PlaylistOwnerFilter(['group:default/team-a']), + }); + rendered.rerender( + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + owners: new PlaylistOwnerFilter(['group:default/team-b']), + }); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.tsx b/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.tsx new file mode 100644 index 0000000000..7def794c6b --- /dev/null +++ b/plugins/playlist/src/components/PlaylistOwnerPicker/PlaylistOwnerPicker.tsx @@ -0,0 +1,134 @@ +/* + * 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 { parseEntityRef } from '@backstage/catalog-model'; +import { humanizeEntityRef } from '@backstage/plugin-catalog-react'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { + Box, + Checkbox, + Chip, + FormControlLabel, + TextField, + Typography, +} from '@material-ui/core'; +import CheckBoxIcon from '@material-ui/icons/CheckBox'; +import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { Autocomplete } from '@material-ui/lab'; +import React, { useEffect, useMemo, useState } from 'react'; + +import { usePlaylistList } from '../../hooks'; +import { PlaylistFilter } from '../../types'; + +export class PlaylistOwnerFilter implements PlaylistFilter { + constructor(readonly values: string[]) {} + + filterPlaylist(playlist: Playlist): boolean { + return this.values.some(v => playlist.owner === v); + } + + toQueryValue(): string[] { + return this.values; + } +} + +const icon = ; +const checkedIcon = ; + +export const PlaylistOwnerPicker = () => { + const { + updateFilters, + backendPlaylists, + filters, + queryParameters: { owners: ownersParameter }, + } = usePlaylistList(); + + const queryParamOwners = useMemo( + () => [ownersParameter].flat().filter(Boolean) as string[], + [ownersParameter], + ); + + const [selectedOwners, setSelectedOwners] = useState( + queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [], + ); + + // Set selected owners on query parameter updates; this happens at initial page load and from + // external updates to the page location. + useEffect(() => { + if (queryParamOwners.length) { + setSelectedOwners(queryParamOwners); + } + }, [queryParamOwners]); + + useEffect(() => { + updateFilters({ + owners: selectedOwners.length + ? new PlaylistOwnerFilter(selectedOwners) + : undefined, + }); + }, [selectedOwners, updateFilters]); + + const availableOwners = useMemo( + () => [...new Set(backendPlaylists.map(p => p.owner))].sort(), + [backendPlaylists], + ); + + if (!availableOwners.length) return null; + + return ( + + + Owner + setSelectedOwners(value)} + renderTags={(values: string[], getTagProps: Function) => + values.map((val, index) => ( + + )) + } + renderOption={(option, { selected }) => ( + + } + label={humanizeEntityRef(parseEntityRef(option), { + defaultKind: 'group', + })} + /> + )} + size="small" + popupIcon={} + renderInput={params => } + /> + + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistOwnerPicker/index.ts b/plugins/playlist/src/components/PlaylistOwnerPicker/index.ts new file mode 100644 index 0000000000..fcde27e956 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistOwnerPicker/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 * from './PlaylistOwnerPicker'; diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx new file mode 100644 index 0000000000..d1bdf1d46a --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx @@ -0,0 +1,159 @@ +/* + * 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 { + CatalogApi, + catalogApiRef, + entityRouteRef, +} from '@backstage/plugin-catalog-react'; +import { SearchApi, searchApiRef } from '@backstage/plugin-search-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { fireEvent, getByText } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; + +import { AddEntitiesDrawer } from './AddEntitiesDrawer'; + +describe('AddEntitiesDrawer', () => { + const catalogApi: Partial = { + getEntityFacets: jest.fn().mockImplementation(async () => ({ + facets: { + kind: [{ value: 'component' }], + }, + })), + }; + + const mockOnAdd = jest.fn(); + const sampleCurrentEntities = [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'system', + metadata: { namespace: 'default', name: 'test-ent' }, + }, + ]; + + const mockSearchResults = [ + { + type: 'software-catalog', + document: { + title: 'Test Ent', + text: 'This is test ent', + location: '/catalog/default/system/test-ent', + kind: 'system', + }, + }, + { + type: 'software-catalog', + document: { + title: 'Test Ent 2', + text: 'This is test ent 2', + location: '/catalog/foo/component/test-ent2', + kind: 'component', + type: 'library', + }, + }, + { + type: 'software-catalog', + document: { + title: 'Test Ent 3', + text: 'This is test ent 3', + location: '/catalog/bar/api/test-ent3', + kind: 'api', + type: 'openapi', + }, + }, + ]; + + const searchApi: Partial = { + query: jest + .fn() + .mockImplementation(async () => ({ results: mockSearchResults })), + }; + + const element = ( + + + + ); + + const render = async () => + renderInTestApp(element, { + mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef }, + }); + + beforeEach(() => { + mockOnAdd.mockClear(); + }); + + it('should render available entities correctly', async () => { + const rendered = await render(); + expect(searchApi.query).toHaveBeenLastCalledWith({ + filters: {}, + term: '', + types: ['software-catalog'], + }); + + expect(rendered.getByText('Test Ent')).toBeInTheDocument(); + expect(rendered.getByText('This is test ent')).toBeInTheDocument(); + expect(rendered.getByText('Kind: system')).toBeInTheDocument(); + + expect(rendered.getByText('Test Ent 2')).toBeInTheDocument(); + expect(rendered.getByText('This is test ent 2')).toBeInTheDocument(); + expect(rendered.getByText('Kind: component')).toBeInTheDocument(); + expect(rendered.getByText('Type: library')).toBeInTheDocument(); + + expect(rendered.getByText('Test Ent 3')).toBeInTheDocument(); + expect(rendered.getByText('This is test ent 3')).toBeInTheDocument(); + expect(rendered.getByText('Kind: api')).toBeInTheDocument(); + expect(rendered.getByText('Type: openapi')).toBeInTheDocument(); + }); + + it('should disable options that are already added', async () => { + const rendered = await render(); + + const addButtons = rendered.getAllByTestId('entity-drawer-add-button'); + expect(addButtons.length).toEqual(3); + + expect(getByText(addButtons[0], 'Added')).toBeInTheDocument(); + expect(addButtons[0]).toBeDisabled(); + + expect(getByText(addButtons[1], 'Add')).toBeInTheDocument(); + expect(addButtons[1]).not.toBeDisabled(); + + expect(getByText(addButtons[2], 'Add')).toBeInTheDocument(); + expect(addButtons[2]).not.toBeDisabled(); + }); + + it('should add entities correctly', async () => { + const rendered = await render(); + + act(() => { + fireEvent.click(rendered.getAllByTestId('entity-drawer-add-button')[1]); + }); + + expect(mockOnAdd).toHaveBeenCalledWith('component:foo/test-ent2'); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx new file mode 100644 index 0000000000..05dd4da231 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx @@ -0,0 +1,239 @@ +/* + * 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, + getCompoundEntityRef, + stringifyEntityRef, +} from '@backstage/catalog-model'; +import { useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; +import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; +import { + SearchBar, + SearchContextProvider, + SearchFilter, + SearchResult, + SearchResultPager, + useSearch, +} from '@backstage/plugin-search-react'; +import { + Box, + Button, + Chip, + createStyles, + Divider, + Drawer, + Grid, + List, + ListItem, + ListItemSecondaryAction, + ListItemText, + makeStyles, + Paper, + Theme, + Typography, +} from '@material-ui/core'; +import React, { useCallback, useEffect, useMemo } from 'react'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + paper: { + width: '50%', + padding: theme.spacing(2.5), + }, + searchBarContainer: { + borderRadius: 30, + display: 'flex', + height: '2.4em', + }, + gridContainer: { + height: '100%', + }, + searchResults: { + overflow: 'auto', + }, + itemContainer: { + flexWrap: 'wrap', + paddingRight: '75px', + }, + itemText: { + width: '100%', + wordBreak: 'break-word', + marginBottom: '1rem', + }, + }), +); + +const RestrictCatalogIndexResults = () => { + const { setTypes } = useSearch(); + useEffect(() => setTypes(['software-catalog']), [setTypes]); + return null; +}; + +export type AddEntitiesDrawerProps = { + currentEntities: Entity[]; + open: boolean; + onAdd: (entityRef: string) => void; + onClose: () => void; +}; + +export const AddEntitiesDrawer = ({ + currentEntities, + open, + onAdd, + onClose, +}: AddEntitiesDrawerProps) => { + const classes = useStyles(); + const catalogApi = useApi(catalogApiRef); + const entityRoute = useRouteRef(entityRouteRef); + const entityLocationRegex = useMemo(() => { + const forwardSlashRegex = new RegExp('/', 'g'); + const locationRegex = entityRoute({ + namespace: '(?.+?)', + kind: '(?.+?)', + name: '(?.+?)', + }).replace(forwardSlashRegex, '\\/'); + + return new RegExp(`${locationRegex}$`); + }, [entityRoute]); + + const currentEntityLocations = useMemo( + () => + currentEntities.map(entity => + entityRoute(getCompoundEntityRef(entity)).toLocaleLowerCase('en-US'), + ), + [currentEntities, entityRoute], + ); + + const getEntityKinds = async () => { + return ( + await catalogApi.getEntityFacets({ facets: ['kind'] }) + ).facets.kind.map(f => f.value); + }; + + const addEntity = useCallback( + entityResult => { + // TODO (kuangp): this parsing of the location is not great. Ideally `CatalogEntityDocument` + // contains the `metadata.name` field so we can derive the full ref and we only fall back to + // parsing location if it's missing (ie. for older versions) + const { groups } = entityResult.location.match(entityLocationRegex); + if (groups) { + onAdd(stringifyEntityRef(groups)); + } else { + // eslint-disable-next-line no-console + console.error( + `Failed to parse entity ref from entity location: ${entityResult.location}`, + ); + } + }, + [entityLocationRegex, onAdd], + ); + + return ( + + + + + + + Let's find something for your playlist + + + + + + + + + + + + + {({ results }) => ( + + {results.map(({ document }) => ( + + +
+ + + + + + {(document as CatalogEntityDocument).kind && ( + + )} + {(document as CatalogEntityDocument).type && ( + + )} + +
+
+ +
+ ))} +
+ )} +
+ +
+
+
+
+ ); +}; diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx new file mode 100644 index 0000000000..3dfd89fda9 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx @@ -0,0 +1,211 @@ +/* + * 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 { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; +import { + CatalogApi, + catalogApiRef, + entityRouteRef, +} from '@backstage/plugin-catalog-react'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + PermissionApi, + permissionApiRef, +} from '@backstage/plugin-permission-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { Button } from '@material-ui/core'; +import { fireEvent, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; +import { SWRConfig } from 'swr'; + +import { PlaylistApi, playlistApiRef } from '../../api'; +import { PlaylistEntitiesTable } from './PlaylistEntitiesTable'; + +jest.mock('./AddEntitiesDrawer', () => ({ + AddEntitiesDrawer: ({ onAdd, open }: { onAdd: Function; open: boolean }) => + open ? ( + +
+ + {deleting.loading && ( + + )} +
+ + + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx new file mode 100644 index 0000000000..65d3d79be6 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx @@ -0,0 +1,141 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { + PermissionApi, + permissionApiRef, +} from '@backstage/plugin-permission-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { fireEvent, getByText, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; +import { SWRConfig } from 'swr'; + +import { PlaylistApi, playlistApiRef } from '../../api'; +import { PlaylistPage } from './PlaylistPage'; + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useParams: () => ({ playlistId: 'id1' }), +})); + +// Mock out nested components to simplify tests +jest.mock('./PlaylistEntitiesTable', () => ({ + PlaylistEntitiesTable: () => null, +})); + +jest.mock('./PlaylistHeader', () => ({ + PlaylistHeader: () => null, +})); + +describe('PlaylistPage', () => { + const testPlaylist = { + id: 'id1', + name: 'playlist-1', + description: 'test description', + owner: 'group:default/some-owner', + public: true, + entities: 1, + followers: 2, + isFollowing: false, + }; + + const errorApi: Partial = { post: jest.fn() }; + const playlistApi: Partial = { + getPlaylist: jest.fn().mockImplementation(async () => testPlaylist), + followPlaylist: jest.fn().mockImplementation(async () => {}), + unfollowPlaylist: jest.fn().mockImplementation(async () => {}), + }; + const mockAuthorize = jest + .fn() + .mockImplementation(async () => ({ result: AuthorizeResult.ALLOW })); + const permissionApi: Partial = { authorize: mockAuthorize }; + + // SWR used by the usePermission hook needs cache to be reset for each test + const element = ( + new Map() }}> + + + + + ); + + beforeEach(() => { + mockAuthorize.mockClear(); + }); + + it('show render the playlist info', async () => { + const rendered = await renderInTestApp(element); + expect(playlistApi.getPlaylist).toHaveBeenCalledWith('id1'); + expect(rendered.getByText('test description')).toBeInTheDocument(); + expect( + rendered.getByTestId('playlist-page-follow-button'), + ).toBeInTheDocument(); + expect( + getByText(rendered.getByTestId('playlist-page-follow-button'), 'Follow'), + ).toBeInTheDocument(); + }); + + it('should not render the follow button if unauthorized', async () => { + mockAuthorize.mockImplementationOnce(async () => ({ + result: AuthorizeResult.DENY, + })); + const rendered = await renderInTestApp(element); + expect(rendered.queryByTestId('playlist-page-follow-button')).toBeNull(); + }); + + it('should reflect and toggle the following state of the playlist', async () => { + const rendered = await renderInTestApp(element); + + act(() => { + fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); + testPlaylist.isFollowing = true; + }); + + await waitFor(() => { + expect(playlistApi.followPlaylist).toHaveBeenCalledWith('id1'); + expect( + getByText( + rendered.getByTestId('playlist-page-follow-button'), + 'Following', + ), + ).toBeInTheDocument(); + }); + + act(() => { + fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); + testPlaylist.isFollowing = false; + }); + + await waitFor(() => { + expect(playlistApi.unfollowPlaylist).toHaveBeenCalledWith('id1'); + expect( + getByText( + rendered.getByTestId('playlist-page-follow-button'), + 'Follow', + ), + ).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.tsx new file mode 100644 index 0000000000..4c9a0edbb7 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.tsx @@ -0,0 +1,133 @@ +/* + * 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 { Content, ErrorPage, Page } from '@backstage/core-components'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { usePermission } from '@backstage/plugin-permission-react'; +import { permissions } from '@backstage/plugin-playlist-common'; +import { + Button, + Card, + CardContent, + CardHeader, + Divider, + LinearProgress, + makeStyles, + Typography, +} from '@material-ui/core'; +import React, { useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +import { playlistApiRef } from '../../api'; +import { PlaylistEntitiesTable } from './PlaylistEntitiesTable'; +import { PlaylistHeader } from './PlaylistHeader'; + +const useStyles = makeStyles({ + followButton: { + top: '6px', + right: '8px', + }, +}); + +export const PlaylistPage = () => { + const classes = useStyles(); + const errorApi = useApi(errorApiRef); + const playlistApi = useApi(playlistApiRef); + const { playlistId } = useParams(); + + const [{ value: playlist, loading, error }, loadPlaylist] = useAsyncFn( + () => playlistApi.getPlaylist(playlistId!), + [playlistApi], + ); + + useEffect(() => { + loadPlaylist(); + }, [loadPlaylist]); + + const { allowed: followAllowed } = usePermission({ + permission: permissions.playlistFollowersUpdate, + resourceRef: playlist?.id, + }); + + const [{ loading: loadingFollowRequest }, followPlaylist] = + useAsyncFn(async () => { + try { + if (playlist!.isFollowing) { + await playlistApi.unfollowPlaylist(playlist!.id); + } else { + await playlistApi.followPlaylist(playlist!.id); + } + + loadPlaylist(); + } catch (e) { + errorApi.post(e); + } + }, [errorApi, loadPlaylist, playlist, playlistApi]); + + if (error) { + return ( + + ); + } + + return ( + <> + {loading && } + + {playlist && ( + <> + + + + + {playlist.isFollowing ? 'Following' : 'Follow'} + + ) + } + /> + + + + {playlist.description} + + + +
+ +
+ + )} +
+ + ); +}; diff --git a/plugins/playlist/src/components/PlaylistPage/index.ts b/plugins/playlist/src/components/PlaylistPage/index.ts new file mode 100644 index 0000000000..695b243cd0 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistPage/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 * from './PlaylistPage'; diff --git a/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.test.tsx b/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.test.tsx new file mode 100644 index 0000000000..84650e4f41 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import { DefaultPlaylistFilters } from '../../hooks'; +import { MockPlaylistListProvider } from '../../testUtils'; +import { PlaylistSearchBar, PlaylistTextFilter } from './PlaylistSearchBar'; + +describe('PlaylistSearchBar', () => { + it('should display search value and execute set callback', async () => { + const updateFilters = jest.fn(); + + const filters: DefaultPlaylistFilters = { + text: new PlaylistTextFilter('hello'), + }; + + const { getByDisplayValue } = render( + + + , + ); + + const searchInput = getByDisplayValue('hello'); + expect(searchInput).toBeInTheDocument(); + + fireEvent.change(searchInput, { target: { value: 'world' } }); + await waitFor(() => expect(updateFilters.mock.calls.length).toBe(1)); + expect(updateFilters).toHaveBeenCalledWith({ + text: new PlaylistTextFilter('world'), + }); + + fireEvent.change(searchInput, { target: { value: '' } }); + await waitFor(() => expect(updateFilters.mock.calls.length).toBe(2)); + expect(updateFilters).toHaveBeenCalledWith({ + text: undefined, + }); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.tsx b/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.tsx new file mode 100644 index 0000000000..94a22a23f5 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSearchBar/PlaylistSearchBar.tsx @@ -0,0 +1,102 @@ +/* + * 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 { Playlist } from '@backstage/plugin-playlist-common'; +import { + FormControl, + IconButton, + Input, + InputAdornment, + makeStyles, + Toolbar, +} from '@material-ui/core'; +import Clear from '@material-ui/icons/Clear'; +import Search from '@material-ui/icons/Search'; +import React, { useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; + +import { usePlaylistList } from '../../hooks'; +import { PlaylistFilter } from '../../types'; + +export class PlaylistTextFilter implements PlaylistFilter { + constructor(readonly value: string) {} + + filterPlaylist(playlist: Playlist): boolean { + const upperCaseValue = this.value.toLocaleUpperCase('en-US'); + return ( + playlist.name.toLocaleUpperCase('en-US').includes(upperCaseValue) || + !!playlist.description + ?.toLocaleUpperCase('en-US') + .includes(upperCaseValue) + ); + } +} + +const useStyles = makeStyles(_theme => ({ + searchToolbar: { + paddingLeft: 0, + paddingRight: 0, + }, +})); + +export const PlaylistSearchBar = () => { + const classes = useStyles(); + + const { filters, updateFilters } = usePlaylistList(); + const [search, setSearch] = useState(filters.text?.value ?? ''); + + useDebounce( + () => { + updateFilters({ + text: search.length ? new PlaylistTextFilter(search) : undefined, + }); + }, + 250, + [search, updateFilters], + ); + + return ( + + + setSearch(event.target.value)} + value={search} + startAdornment={ + + + + } + endAdornment={ + + setSearch('')} + edge="end" + disabled={search.length === 0} + > + + + + } + /> + + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistSearchBar/index.ts b/plugins/playlist/src/components/PlaylistSearchBar/index.ts new file mode 100644 index 0000000000..65b7e181cf --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSearchBar/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 * from './PlaylistSearchBar'; diff --git a/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx new file mode 100644 index 0000000000..9317bfd4c1 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx @@ -0,0 +1,68 @@ +/* + * 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 { fireEvent, getByRole, render, waitFor } from '@testing-library/react'; +import { act } from '@testing-library/react-hooks'; +import React from 'react'; + +import { MockPlaylistListProvider } from '../../testUtils'; +import { + DefaultPlaylistSortTypes, + DefaultSortCompareFunctions, + PlaylistSortPicker, +} from './PlaylistSortPicker'; + +describe('PlaylistSortPicker', () => { + it('should update sort based on selection', async () => { + const updateSort = jest.fn(); + + const { getByText, getByTestId } = render( + + + , + ); + + act(() => { + fireEvent.mouseDown( + getByRole(getByTestId('sort-picker-select'), 'button'), + ); + }); + const abcSort = getByText('Alphabetical'); + expect(abcSort).toBeInTheDocument(); + + fireEvent.click(abcSort); + await waitFor(() => { + expect(updateSort).toHaveBeenLastCalledWith( + DefaultSortCompareFunctions[DefaultPlaylistSortTypes.alphabetical], + ); + }); + + act(() => { + fireEvent.mouseDown( + getByRole(getByTestId('sort-picker-select'), 'button'), + ); + }); + const entitiesSort = getByText('# Entities'); + expect(entitiesSort).toBeInTheDocument(); + + fireEvent.click(entitiesSort); + await waitFor(() => { + expect(updateSort).toHaveBeenLastCalledWith( + DefaultSortCompareFunctions[DefaultPlaylistSortTypes.numEntities], + ); + }); + }); +}); diff --git a/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.tsx b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.tsx new file mode 100644 index 0000000000..21c961eb91 --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.tsx @@ -0,0 +1,115 @@ +/* + * 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 { Playlist } from '@backstage/plugin-playlist-common'; +import { + ListSubheader, + makeStyles, + MenuItem, + Select, + Typography, +} from '@material-ui/core'; +import SwapVertIcon from '@material-ui/icons/SwapVert'; +import React from 'react'; +import useEffectOnce from 'react-use/lib/useEffectOnce'; + +import { usePlaylistList } from '../../hooks'; +import { PlaylistSortCompareFunction } from '../../types'; + +export const enum DefaultPlaylistSortTypes { + popular = 'popular', + alphabetical = 'alphabetical', + numEntities = 'numEntities', +} + +export const DefaultSortCompareFunctions: { + [type in DefaultPlaylistSortTypes]: PlaylistSortCompareFunction; +} = { + [DefaultPlaylistSortTypes.popular]: (a: Playlist, b: Playlist) => { + if (a.followers < b.followers) { + return 1; + } else if (a.followers > b.followers) { + return -1; + } + return 0; + }, + [DefaultPlaylistSortTypes.alphabetical]: (a: Playlist, b: Playlist) => + a.name.localeCompare(b.name), + [DefaultPlaylistSortTypes.numEntities]: (a: Playlist, b: Playlist) => { + if (a.entities < b.entities) { + return 1; + } else if (a.entities > b.entities) { + return -1; + } + return 0; + }, +}; + +const sortTypeLabels = { + [DefaultPlaylistSortTypes.popular]: 'Popular', + [DefaultPlaylistSortTypes.alphabetical]: 'Alphabetical', + [DefaultPlaylistSortTypes.numEntities]: '# Entities', +}; + +const useStyles = makeStyles({ + select: { + width: '10rem', + marginRight: '1rem', + }, + icon: { + verticalAlign: 'bottom', + }, +}); + +export const PlaylistSortPicker = () => { + const classes = useStyles(); + const { updateSort } = usePlaylistList(); + + useEffectOnce(() => + updateSort(DefaultSortCompareFunctions[DefaultPlaylistSortTypes.popular]), + ); + + return ( + + ); +}; diff --git a/plugins/playlist/src/components/PlaylistSortPicker/index.ts b/plugins/playlist/src/components/PlaylistSortPicker/index.ts new file mode 100644 index 0000000000..04ea5268ef --- /dev/null +++ b/plugins/playlist/src/components/PlaylistSortPicker/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 * from './PlaylistSortPicker'; diff --git a/plugins/playlist/src/components/Router/Router.test.tsx b/plugins/playlist/src/components/Router/Router.test.tsx new file mode 100644 index 0000000000..ea8620ec42 --- /dev/null +++ b/plugins/playlist/src/components/Router/Router.test.tsx @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { PlaylistIndexPage } from '../PlaylistIndexPage'; +import { PlaylistPage } from '../PlaylistPage'; +import { Router } from './Router'; +import { renderInTestApp } from '@backstage/test-utils'; + +jest.mock('../PlaylistIndexPage', () => ({ + PlaylistIndexPage: jest.fn(() => null), +})); + +jest.mock('../PlaylistPage', () => ({ + PlaylistPage: jest.fn(() => null), +})); + +describe('Router', () => { + beforeEach(() => { + (PlaylistPage as jest.Mock).mockClear(); + (PlaylistIndexPage as jest.Mock).mockClear(); + }); + describe('/', () => { + it('should render the PlaylistIndexPage', async () => { + await renderInTestApp(); + expect(PlaylistIndexPage).toHaveBeenCalled(); + }); + }); + + describe('/:playlistId', () => { + it('should render the PlaylistPage page', async () => { + await renderInTestApp(, { + routeEntries: ['/my-playlist'], + }); + expect(PlaylistPage).toHaveBeenCalled(); + }); + }); +}); diff --git a/plugins/playlist/src/components/Router/Router.tsx b/plugins/playlist/src/components/Router/Router.tsx new file mode 100644 index 0000000000..5791a0817c --- /dev/null +++ b/plugins/playlist/src/components/Router/Router.tsx @@ -0,0 +1,29 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Routes, Route } from 'react-router'; + +import { playlistRouteRef } from '../../routes'; +import { PlaylistIndexPage } from '../PlaylistIndexPage'; +import { PlaylistPage } from '../PlaylistPage'; + +export const Router = () => ( + + } /> + } /> + +); diff --git a/plugins/playlist/src/components/Router/index.ts b/plugins/playlist/src/components/Router/index.ts new file mode 100644 index 0000000000..6606629fee --- /dev/null +++ b/plugins/playlist/src/components/Router/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 * from './Router'; diff --git a/plugins/playlist/src/components/index.ts b/plugins/playlist/src/components/index.ts new file mode 100644 index 0000000000..2be300ac51 --- /dev/null +++ b/plugins/playlist/src/components/index.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './CreatePlaylistButton'; +export * from './EntityPlaylistDialog'; +export * from './PersonalListPicker'; +export * from './PlaylistCard'; +export * from './PlaylistEditDialog'; +export * from './PlaylistIndexPage'; +export * from './PlaylistList'; +export * from './PlaylistOwnerPicker'; +export * from './PlaylistPage'; +export * from './PlaylistSearchBar'; +export * from './PlaylistSortPicker'; diff --git a/plugins/playlist/src/hooks/index.ts b/plugins/playlist/src/hooks/index.ts new file mode 100644 index 0000000000..316121b515 --- /dev/null +++ b/plugins/playlist/src/hooks/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 * from './usePlaylistList'; diff --git a/plugins/playlist/src/hooks/usePlaylistList.test.tsx b/plugins/playlist/src/hooks/usePlaylistList.test.tsx new file mode 100644 index 0000000000..d04996513e --- /dev/null +++ b/plugins/playlist/src/hooks/usePlaylistList.test.tsx @@ -0,0 +1,225 @@ +/* + * 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 { + ConfigApi, + configApiRef, + IdentityApi, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { TestApiProvider } from '@backstage/test-utils'; +import { act, renderHook } from '@testing-library/react-hooks'; +import qs from 'qs'; +import React, { PropsWithChildren } from 'react'; +import { MemoryRouter } from 'react-router'; +import { PlaylistApi, playlistApiRef } from '../api'; +import { + DefaultSortCompareFunctions, + DefaultPlaylistSortTypes, + PersonalListFilter, + PersonalListFilterValue, + PersonalListPicker, + PlaylistOwnerPicker, +} from '../components'; +import { PlaylistListProvider, usePlaylistList } from './usePlaylistList'; + +const playlists: Playlist[] = [ + { + id: 'id1', + name: 'list-1', + owner: 'user:default/guest', + public: true, + entities: 2, + followers: 5, + isFollowing: false, + }, + { + id: 'id2', + name: 'list-2', + owner: 'group:default/foo', + public: true, + entities: 3, + followers: 2, + isFollowing: true, + }, +]; + +const mockConfigApi = { + getOptionalString: () => '', +} as Partial; + +const mockIdentityApi: Partial = { + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/guest', + ownershipEntityRefs: [], + }), +}; + +const mockPlaylistApi: Partial = { + getAllPlaylists: jest.fn().mockImplementation(async () => playlists), +}; + +const wrapper = ({ + location, + children, +}: PropsWithChildren<{ + location?: string; +}>) => { + return ( + + + + + + {children} + + + + ); +}; + +describe('', () => { + const origReplaceState = window.history.replaceState; + beforeEach(() => { + window.history.replaceState = jest.fn(); + }); + afterEach(() => { + window.history.replaceState = origReplaceState; + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('resolves backend filters', async () => { + const { result, waitForValueToChange } = renderHook( + () => usePlaylistList(), + { + wrapper, + }, + ); + await waitForValueToChange(() => result.current.backendPlaylists); + expect(result.current.backendPlaylists.length).toBe(2); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); + }); + + it('resolves frontend filters', async () => { + const { result, waitFor } = renderHook(() => usePlaylistList(), { + wrapper, + }); + await waitFor(() => !!result.current.playlists.length); + expect(result.current.backendPlaylists.length).toBe(2); + + act(() => + result.current.updateFilters({ + personal: new PersonalListFilter( + PersonalListFilterValue.owned, + playlist => playlist.name === 'list-1', + ), + }), + ); + + await waitFor(() => { + expect(result.current.backendPlaylists.length).toBe(2); + expect(result.current.playlists.length).toBe(1); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalledTimes(1); + }); + }); + + it('resolves query param filter values', async () => { + const query = qs.stringify({ + filters: { personal: 'all', owners: ['user:default/guest'] }, + }); + const { result, waitFor } = renderHook(() => usePlaylistList(), { + wrapper, + initialProps: { + location: `/playlist?${query}`, + }, + }); + await waitFor(() => !!result.current.queryParameters); + expect(result.current.queryParameters).toEqual({ + personal: 'all', + owners: ['user:default/guest'], + }); + }); + + it('does not fetch when only frontend filters change', async () => { + const { result, waitFor } = renderHook(() => usePlaylistList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.playlists.length).toBe(2); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalledTimes(1); + }); + + act(() => + result.current.updateFilters({ + personal: new PersonalListFilter( + PersonalListFilterValue.owned, + playlist => playlist.name === 'list-1', + ), + }), + ); + + await waitFor(() => { + expect(result.current.playlists.length).toBe(1); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalledTimes(1); + }); + }); + + it('applies custom sorting', async () => { + const { result, waitFor } = renderHook(() => usePlaylistList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.playlists.length).toBe(2); + expect(result.current.playlists[0].name).toEqual('list-1'); + expect(result.current.playlists[1].name).toEqual('list-2'); + }); + + act(() => + result.current.updateSort( + DefaultSortCompareFunctions[DefaultPlaylistSortTypes.numEntities], + ), + ); + + await waitFor(() => { + expect(result.current.playlists.length).toBe(2); + expect(result.current.playlists[0].name).toEqual('list-2'); + expect(result.current.playlists[1].name).toEqual('list-1'); + }); + }); + + it('returns an error on playlistApi failure', async () => { + mockPlaylistApi.getAllPlaylists = jest.fn().mockRejectedValue('error'); + const { result, waitFor } = renderHook(() => usePlaylistList(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); + }); +}); diff --git a/plugins/playlist/src/hooks/usePlaylistList.tsx b/plugins/playlist/src/hooks/usePlaylistList.tsx new file mode 100644 index 0000000000..93c0becbfd --- /dev/null +++ b/plugins/playlist/src/hooks/usePlaylistList.tsx @@ -0,0 +1,284 @@ +/* + * 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 { useApi } from '@backstage/core-plugin-api'; +import { Playlist } from '@backstage/plugin-playlist-common'; +import { compact, isEqual } from 'lodash'; +import qs from 'qs'; +import React, { + createContext, + PropsWithChildren, + useCallback, + useContext, + useMemo, + useState, +} from 'react'; +import { useLocation } from 'react-router'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; +import useDebounce from 'react-use/lib/useDebounce'; +import useMountedState from 'react-use/lib/useMountedState'; + +import { playlistApiRef } from '../api'; +import { PersonalListFilter } from '../components/PersonalListPicker'; +import { PlaylistOwnerFilter } from '../components/PlaylistOwnerPicker'; +import { PlaylistTextFilter } from '../components/PlaylistSearchBar'; +import { + DefaultPlaylistSortTypes, + DefaultSortCompareFunctions, +} from '../components/PlaylistSortPicker'; +import { PlaylistFilter, PlaylistSortCompareFunction } from '../types'; + +class NoopFilter implements PlaylistFilter { + getBackendFilters() { + return { '': null }; + } +} + +export type DefaultPlaylistFilters = { + noop?: NoopFilter; + owners?: PlaylistOwnerFilter; + personal?: PersonalListFilter; + text?: PlaylistTextFilter; +}; + +export type PlaylistListContextProps< + PlaylistFilters extends DefaultPlaylistFilters = DefaultPlaylistFilters, +> = { + /** + * The currently registered filters, adhering to the shape of DefaultPlaylistFilters + */ + filters: PlaylistFilters; + + /** + * The resolved list of playlists, after all filters are applied. + */ + playlists: Playlist[]; + + /** + * The resolved list of playlists, after _only playlist-backend_ filters are applied. + */ + backendPlaylists: Playlist[]; + + /** + * Update one or more of the registered filters. Optional filters can be set to `undefined` to + * reset the filter. + */ + updateFilters: ( + filters: + | Partial + | ((prevFilters: PlaylistFilters) => Partial), + ) => void; + + /** + * Update the compare function used to sort playlists. + */ + updateSort: (compareFn: PlaylistSortCompareFunction) => void; + + /** + * Filter values from query parameters. + */ + queryParameters: Partial>; + + loading: boolean; + error?: Error; +}; + +export const PlaylistListContext = createContext< + PlaylistListContextProps | undefined +>(undefined); + +const reduceBackendFilters = ( + filters: PlaylistFilter[], +): Record => { + return filters.reduce((compoundFilter, filter) => { + return { + ...compoundFilter, + ...(filter.getBackendFilters ? filter.getBackendFilters() : {}), + }; + }, {} as Record); +}; + +type OutputState = { + appliedFilters: PlaylistFilters; + playlists: Playlist[]; + backendPlaylists: Playlist[]; +}; + +export const PlaylistListProvider = < + PlaylistFilters extends DefaultPlaylistFilters, +>({ + children, +}: PropsWithChildren<{}>) => { + const isMounted = useMountedState(); + const playlistApi = useApi(playlistApiRef); + const [sortCompareFn, setSortCompareFn] = + useState( + () => DefaultSortCompareFunctions[DefaultPlaylistSortTypes.popular], + ); + const [requestedFilters, setRequestedFilters] = useState( + {} as PlaylistFilters, + ); + + // We use react-router's useLocation hook so updates from external sources trigger an update to + // the queryParameters in outputState. Updates from this hook use replaceState below and won't + // trigger a useLocation change; this would instead come from an external source, such as a manual + // update of the URL or two sidebar links with different filters. + const location = useLocation(); + const queryParameters = useMemo( + () => + (qs.parse(location.search, { + ignoreQueryPrefix: true, + }).filters ?? {}) as Record, + [location], + ); + + const [outputState, setOutputState] = useState>({ + appliedFilters: { + noop: new NoopFilter(), // Init with a noop filter to trigger intial request + } as PlaylistFilters, + playlists: [], + backendPlaylists: [], + }); + + // The main async filter worker. Note that while it has a lot of dependencies + // in terms of its implementation, the triggering only happens (debounced) + // based on the requested filters/sortCompareFn changing. + const [{ loading, error }, refresh] = useAsyncFn( + async () => { + const compacted: PlaylistFilter[] = compact( + Object.values(requestedFilters), + ); + const playlistFilter = (p: Playlist) => + compacted.every( + filter => !filter.filterPlaylist || filter.filterPlaylist(p), + ); + const backendFilter = reduceBackendFilters(compacted); + const previousBackendFilter = reduceBackendFilters( + compact(Object.values(outputState.appliedFilters)), + ); + + const queryParams = Object.keys(requestedFilters).reduce( + (params, key) => { + const filter: PlaylistFilter | undefined = + requestedFilters[key as keyof PlaylistFilters]; + if (filter?.toQueryValue) { + params[key] = filter.toQueryValue(); + } + return params; + }, + {} as Record, + ); + + if (!isEqual(previousBackendFilter, backendFilter)) { + const response = await playlistApi.getAllPlaylists({ + filter: backendFilter, + }); + setOutputState({ + appliedFilters: requestedFilters, + backendPlaylists: response, + playlists: response.filter(playlistFilter).sort(sortCompareFn), + }); + } else { + setOutputState({ + appliedFilters: requestedFilters, + backendPlaylists: outputState.backendPlaylists, + playlists: outputState.backendPlaylists + .filter(playlistFilter) + .sort(sortCompareFn), + }); + } + + if (isMounted()) { + const oldParams = qs.parse(location.search, { + ignoreQueryPrefix: true, + }); + const newParams = qs.stringify( + { ...oldParams, filters: queryParams }, + { addQueryPrefix: true, arrayFormat: 'repeat' }, + ); + const newUrl = `${window.location.pathname}${newParams}`; + // We use direct history manipulation since useSearchParams and + // useNavigate in react-router-dom cause unnecessary extra rerenders. + // Also make sure to replace the state rather than pushing, since we + // don't want there to be back/forward slots for every single filter + // change. + window.history?.replaceState(null, document.title, newUrl); + } + }, + [ + playlistApi, + queryParameters, + requestedFilters, + sortCompareFn, + outputState, + ], + { loading: true }, + ); + + // Slight debounce on the refresh, since (especially on page load) several + // filters will be calling this in rapid succession. + useDebounce(refresh, 10, [requestedFilters, sortCompareFn]); + + const updateFilters = useCallback( + ( + update: + | Partial + | ((prevFilters: PlaylistFilters) => Partial), + ) => { + setRequestedFilters(prevFilters => { + const newFilters = + typeof update === 'function' ? update(prevFilters) : update; + return { ...prevFilters, ...newFilters }; + }); + }, + [], + ); + + const updateSort = useCallback( + (compareFn: PlaylistSortCompareFunction) => + setSortCompareFn(() => compareFn), + [], + ); + + const value = useMemo( + () => ({ + filters: outputState.appliedFilters, + playlists: outputState.playlists, + backendPlaylists: outputState.backendPlaylists, + updateFilters, + updateSort, + queryParameters, + loading, + error, + }), + [outputState, updateFilters, updateSort, queryParameters, loading, error], + ); + + return ( + + {children} + + ); +}; + +export function usePlaylistList< + PlaylistFilters extends DefaultPlaylistFilters = DefaultPlaylistFilters, +>(): PlaylistListContextProps { + const context = useContext(PlaylistListContext); + if (!context) + throw new Error('usePlaylistList must be used within PlaylistListProvider'); + return context; +} diff --git a/plugins/playlist/src/index.ts b/plugins/playlist/src/index.ts new file mode 100644 index 0000000000..3b7004ce22 --- /dev/null +++ b/plugins/playlist/src/index.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. + */ + +/** + * Playlist frontend plugin + * + * @packageDocumentation + */ +export type { EntityPlaylistDialogProps } from './components'; +export { + EntityPlaylistDialog, + playlistPlugin, + PlaylistIndexPage, +} from './plugin'; +export * from './api'; diff --git a/plugins/playlist/src/plugin.test.ts b/plugins/playlist/src/plugin.test.ts new file mode 100644 index 0000000000..a2dfc7fcd7 --- /dev/null +++ b/plugins/playlist/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * 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 { playlistPlugin } from './plugin'; + +describe('playlist', () => { + it('should export plugin', () => { + expect(playlistPlugin).toBeDefined(); + }); +}); diff --git a/plugins/playlist/src/plugin.ts b/plugins/playlist/src/plugin.ts new file mode 100644 index 0000000000..8e73fffe37 --- /dev/null +++ b/plugins/playlist/src/plugin.ts @@ -0,0 +1,74 @@ +/* + * 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 { + createApiFactory, + createComponentExtension, + createPlugin, + createRoutableExtension, + discoveryApiRef, + fetchApiRef, +} from '@backstage/core-plugin-api'; + +import { playlistApiRef, PlaylistClient } from './api'; +import { rootRouteRef } from './routes'; + +/** + * @public + */ +export const playlistPlugin = createPlugin({ + id: 'playlist', + routes: { + root: rootRouteRef, + }, + apis: [ + createApiFactory({ + api: playlistApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, fetchApi }) => + new PlaylistClient({ discoveryApi, fetchApi }), + }), + ], +}); + +/** + * @public + */ +export const PlaylistIndexPage = playlistPlugin.provide( + createRoutableExtension({ + name: 'PlaylistIndexPage', + component: () => import('./components/Router').then(m => m.Router), + mountPoint: rootRouteRef, + }), +); + +/** + * @public + */ +export const EntityPlaylistDialog = playlistPlugin.provide( + createComponentExtension({ + name: 'EntityPlaylistDialog', + component: { + lazy: () => + import('./components/EntityPlaylistDialog').then( + m => m.EntityPlaylistDialog, + ), + }, + }), +); diff --git a/plugins/playlist/src/routes.ts b/plugins/playlist/src/routes.ts new file mode 100644 index 0000000000..632dc06439 --- /dev/null +++ b/plugins/playlist/src/routes.ts @@ -0,0 +1,26 @@ +/* + * 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 { createRouteRef, createSubRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + id: 'playlist:index-page', +}); + +export const playlistRouteRef = createSubRouteRef({ + id: 'playlist:playlist-page', + parent: rootRouteRef, + path: '/:playlistId', +}); diff --git a/plugins/playlist/src/setupTests.ts b/plugins/playlist/src/setupTests.ts new file mode 100644 index 0000000000..9bb3e72355 --- /dev/null +++ b/plugins/playlist/src/setupTests.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. + */ +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/playlist/src/testUtils/MockPlaylistListProvider.tsx b/plugins/playlist/src/testUtils/MockPlaylistListProvider.tsx new file mode 100644 index 0000000000..2acef15e14 --- /dev/null +++ b/plugins/playlist/src/testUtils/MockPlaylistListProvider.tsx @@ -0,0 +1,102 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { + PropsWithChildren, + useCallback, + useMemo, + useState, +} from 'react'; +import { + DefaultPlaylistSortTypes, + DefaultSortCompareFunctions, +} from '../components'; +import { + DefaultPlaylistFilters, + PlaylistListContext, + PlaylistListContextProps, +} from '../hooks'; +import { PlaylistSortCompareFunction } from '../types'; + +export const MockPlaylistListProvider = ({ + children, + value, +}: PropsWithChildren<{ + value?: Partial; +}>) => { + const [filters, setFilters] = useState( + value?.filters ?? {}, + ); + + const [_, setSortCompareFn] = useState( + () => DefaultSortCompareFunctions[DefaultPlaylistSortTypes.popular], + ); + + const updateFilters = useCallback( + ( + update: + | Partial + | (( + prevFilters: DefaultPlaylistFilters, + ) => Partial), + ) => { + setFilters(prevFilters => { + const newFilters = + typeof update === 'function' ? update(prevFilters) : update; + return { ...prevFilters, ...newFilters }; + }); + }, + [], + ); + + const updateSort = useCallback( + (compareFn: PlaylistSortCompareFunction) => + setSortCompareFn(() => compareFn), + [], + ); + + // Memoize the default values since pickers have useEffect triggers on these; naively defaulting + // below with `?? ` breaks referential equality on subsequent updates. + const defaultValues = useMemo( + () => ({ + playlists: [], + backendPlaylists: [], + queryParameters: {}, + }), + [], + ); + + const resolvedValue: PlaylistListContextProps = useMemo( + () => ({ + playlists: value?.playlists ?? defaultValues.playlists, + backendPlaylists: + value?.backendPlaylists ?? defaultValues.backendPlaylists, + updateFilters: value?.updateFilters ?? updateFilters, + filters, + updateSort: value?.updateSort ?? updateSort, + loading: value?.loading ?? false, + queryParameters: value?.queryParameters ?? defaultValues.queryParameters, + error: value?.error, + }), + [value, defaultValues, filters, updateFilters, updateSort], + ); + + return ( + + {children} + + ); +}; diff --git a/plugins/playlist/src/testUtils/index.ts b/plugins/playlist/src/testUtils/index.ts new file mode 100644 index 0000000000..9b6f333a59 --- /dev/null +++ b/plugins/playlist/src/testUtils/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 * from './MockPlaylistListProvider'; diff --git a/plugins/playlist/src/types.ts b/plugins/playlist/src/types.ts new file mode 100644 index 0000000000..fbd348f98a --- /dev/null +++ b/plugins/playlist/src/types.ts @@ -0,0 +1,27 @@ +/* + * 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 { Playlist } from '@backstage/plugin-playlist-common'; + +export type PlaylistFilter = { + getBackendFilters?: () => Record; + + filterPlaylist?: (playlist: Playlist) => boolean; + + toQueryValue?: () => string | string[]; +}; + +export type PlaylistSortCompareFunction = (a: Playlist, b: Playlist) => number; diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx index 35d1f376e5..c14dfdfa7e 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx @@ -62,7 +62,7 @@ export const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => { defaultValues, valuesDebounceMs, ); - const { filters, setFilters } = useSearch(); + const { filters, setFilters, setPageCursor } = useSearch(); const filterValue = (filters[name] as string | string[] | undefined) || (multiple ? [] : null); @@ -79,6 +79,7 @@ export const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => { } return { ...others }; }); + setPageCursor(undefined); }; // Provide the input field. diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx index 89a1818e8d..27fbae237c 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx @@ -33,6 +33,7 @@ describe('SearchFilter', () => { term: '', filters: {}, types: [], + pageCursor: 'abc123', }; const label = 'Field'; @@ -138,7 +139,10 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters: { field: [values[0]] } }), + expect.objectContaining({ + filters: { field: [values[0]] }, + pageCursor: undefined, + }), ); }); @@ -146,7 +150,7 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters: {} }), + expect.objectContaining({ filters: {}, pageCursor: undefined }), ); }); }); @@ -170,6 +174,7 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { ...filters, field: [values[0]] }, + pageCursor: undefined, }), ); }); @@ -178,7 +183,7 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters }), + expect.objectContaining({ filters, pageCursor: undefined }), ); }); }); @@ -337,6 +342,7 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { [name]: values[0] }, + pageCursor: undefined, }), ); }); @@ -353,6 +359,7 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: {}, + pageCursor: undefined, }), ); }); @@ -388,6 +395,7 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { ...filters, [name]: values[0] }, + pageCursor: undefined, }), ); }); @@ -402,7 +410,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters }), + expect.objectContaining({ filters, pageCursor: undefined }), ); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx index 2a6d7baafa..958caf0927 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx @@ -82,7 +82,7 @@ export const CheckboxFilter = (props: SearchFilterComponentProps) => { valuesDebounceMs, } = props; const classes = useStyles(); - const { filters, setFilters } = useSearch(); + const { filters, setFilters, setPageCursor } = useSearch(); useDefaultFilterValue(name, defaultValue); const asyncValues = typeof givenValues === 'function' ? givenValues : undefined; @@ -106,6 +106,7 @@ export const CheckboxFilter = (props: SearchFilterComponentProps) => { const items = checked ? [...rest, value] : rest; return items.length ? { ...others, [name]: items } : others; }); + setPageCursor(undefined); }; return ( @@ -161,7 +162,7 @@ export const SelectFilter = (props: SearchFilterComponentProps) => { defaultValues, valuesDebounceMs, ); - const { filters, setFilters } = useSearch(); + const { filters, setFilters, setPageCursor } = useSearch(); const handleChange = (e: ChangeEvent<{ value: unknown }>) => { const { @@ -172,6 +173,7 @@ export const SelectFilter = (props: SearchFilterComponentProps) => { const { [name]: filter, ...others } = prevFilters; return value ? { ...others, [name]: value as string } : others; }); + setPageCursor(undefined); }; return ( From 2028a73c9661b1589e2e4f15faab6427200791f9 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Tue, 6 Sep 2022 17:36:17 -0400 Subject: [PATCH 33/95] refactor(playlists): address review comments Signed-off-by: Phil Kuang --- .changeset/calm-snakes-tap.md | 2 +- .github/CODEOWNERS | 4 + microsite/static/img/playlist-logo.png | Bin 14734 -> 14844 bytes packages/backend/src/plugins/playlist.ts | 22 ++--- packages/core-components/api-report.md | 24 +++-- .../src/components/Table/Table.tsx | 2 +- .../HeaderActionMenu.test.tsx | 6 +- .../HeaderActionMenu/HeaderActionMenu.tsx | 16 ++-- .../src/layout/HeaderActionMenu/index.ts | 2 +- plugins/playlist-backend/README.md | 21 ++--- plugins/playlist-backend/api-report.md | 7 +- .../migrations/20220701011329_init.js | 8 +- plugins/playlist-backend/package.json | 18 ++-- .../src/service/ListPlaylistsFilter.ts | 13 ++- .../src/service/router.test.ts | 71 +++++++++++++-- .../playlist-backend/src/service/router.ts | 55 ++++++++++-- .../src/service/standaloneServer.ts | 5 +- plugins/playlist-common/package.json | 4 +- plugins/playlist/api-report.md | 12 +-- plugins/playlist/package.json | 23 +++-- plugins/playlist/src/api/PlaylistApi.ts | 3 +- .../playlist/src/api/PlaylistClient.test.ts | 24 ++++- plugins/playlist/src/api/PlaylistClient.ts | 3 +- .../EntityPlaylistDialog.tsx | 7 +- .../PlaylistEntitiesTable.test.tsx | 48 ++-------- .../PlaylistPage/PlaylistEntitiesTable.tsx | 48 ++-------- yarn.lock | 83 +++++++++++++++++- 27 files changed, 330 insertions(+), 201 deletions(-) diff --git a/.changeset/calm-snakes-tap.md b/.changeset/calm-snakes-tap.md index 6b853da53d..6fdf092ede 100644 --- a/.changeset/calm-snakes-tap.md +++ b/.changeset/calm-snakes-tap.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Export `HeaderActionMenu` and expose default `Table` icons via `Table.tableIcons` +Export `HeaderActionMenu` and expose default `Table` icons via `Table.icons` diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f00771d29d..b0f1e828cd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,6 +16,8 @@ yarn.lock @backstage/reviewers @backst /docs/plugins/integrating-search-into-plugins.md @backstage/reviewers @backstage/techdocs-core /packages/techdocs-cli @backstage/reviewers @backstage/techdocs-core /packages/techdocs-cli-embedded-app @backstage/reviewers @backstage/techdocs-core +/plugins/adr @backstage/reviewers @kuangp +/plugins/adr-* @backstage/reviewers @kuangp /plugins/allure @backstage/reviewers @deepak-bhardwaj-ps /plugins/apache-airflow @backstage/reviewers @cmpadden /plugins/api-docs @backstage/reviewers @backstage/sda-se-reviewers @@ -47,6 +49,8 @@ yarn.lock @backstage/reviewers @backst /plugins/kubernetes @backstage/reviewers @backstage/warpspeed /plugins/kubernetes-* @backstage/reviewers @backstage/warpspeed /plugins/newrelic-dashboard @backstage/reviewers @mufaddal7 +/plugins/playlist @backstage/reviewers @kuangp +/plugins/playlist-* @backstage/reviewers @kuangp /plugins/scaffolder-backend-module-rails @backstage/reviewers @angeliski /plugins/scaffolder-backend-module-yeoman @backstage/reviewers @pawelmitka /plugins/search @backstage/reviewers @backstage/techdocs-core diff --git a/microsite/static/img/playlist-logo.png b/microsite/static/img/playlist-logo.png index b5c8d9940175d6221c1bf1cdf9ab473e5793a5fb..333a9f832a48f430f415c94cc9e1346d5a04ce20 100644 GIT binary patch literal 14844 zcmeHudpuNY`?nb*L&dDxItj~6B}o)fIn0uYP_%iTgdEyQwR1j%oMyJlv~!pqHrYaL zp_4;|ipEs-CPar_D5q^3D#sbyDPz3Xa(JHi^V{#=@B4W_k3ag%$Gz@#-S>T6-|KrF z?$xD3*5=D)*U3sqNG!M5&#;w{Aad}3-^i_eA^D9Aze}(Q_U6(qcp6acYXp8n?;+NgGLN&;1+-{y;X7Y=fuH?aQt1V>? z+S--BVmq$PIZxUoD_J9Ba`(!%oHZNWPo$`4dwySgDb;l(W?VaMWpCTixv_H@C!LMM zdg@IgGDh!>PHK)CO!XHB%h1Ub6k|#dh$Qkq$Voq*G_sug14dEOO{@7w6!g$W6utY< z@W8@T6m7%bnSGhHg+Orlm49sEZvx@7+<&CXkZZPVlV7>83VDCvGnylE{i5S0)xGu$*Mi9- z6N&!k)m#3whF`Vj)5!{)x3O0$u&rhdx8O^ zRq1ZI4u>&o9ZP9d?D~Bs({tJPkFJnN-TU9}IbJ{%E(_||fVq)i#b-(Verg25qm})- zb+R?5%|4?fvhFGhC(cAu|6fez`qPdl`~Qh$+!#zFkz-L<@#?>f24UskAJRP>2)kcy zRyr@i`VI22?YH=5kb2P$_QgJtt#Hh5}Xe2;m}BS~&A6FW{Iw5<8vp9ZS9k`wfs z%c2n$jj-qm|4%(ZPsf%1^4R+Gz?#dYEY*YckLIUk?-v+5TuV%%`fb1l7 z&AR4*`(d*Mqi;N~o3MMJ@mhL-Q_s{L<~5%jYX)8-N(0qNaw2|l0yiHx% z0iGh629oe;yIe3#*=O+bG%OYAaZC*_HnlmxPp6KQemDyJrB;ICb>uxDMftyzB6YWp1U>GPBHdKnJ6o;m!6}!Ya!EDA=Hm@aqrtQ*AGq(* zn9P1J>X<1$(G=#X{^p)I7oIe&@UZ~k^+&yZflW)v`}J{TkjS1u>58u^cEmB~xg18# zWyv+Pl8C$dVD68M{uq4XMVMzA`(o1^^*bixV?AKgfX1fJ`Ku`$Z-|s&vt}@l{`Jrk z>p-ou!3sv>0Tt%oPaXDwuvK=cSstIbOch0A)+8RBi)|%a@v(YM6z$C@c(x;-;rFq;c4#2@th}#+Ph7JX!{oMaN}CJbXB_act40C=XjH0FOT@buQ5@ZfS^+a?2WdH*10Cza>!dG+oXsXNv#C?^fj zlV;i0^XP9`8`1yHnJ?Nu5$(iULD?pW)l%*&%`StsZ-BP_Zw05=4zBg@)r(+5{#3OU zRWxzDD8c#+rsB{PIHvIf4-YP_F?&xeLT;V_>so`wciR$ncQ?m>e8BW{*IayIQA>-^ zSoDYgzgfeu;X}%7sG_p!D>SGs^w(FsjecZa3oOiw--tR{IL=1nWGKL_;yxZ5f~3M( zW-(Oa8e7cK7IU=!)*Q_}OVNKcYX7=CkF`Y7pw0CpfBEzvsU0KJv@ZR9RnpGW)7+U! zA$_J}e6nxmsJPFzmS5S?AH(!CJAH!y{jIDUCp`2VYj=>yt(80@$ma+zHGLH>Wv)Ro z14o4YC8sXISxuonUB<^Yzs;QIeh@U+p z+=CJB&oCUmd7P_G-4->S#h%E`PKpX>GbVLg*a=&BMJ5 zaO-ZR@twD(l{=~J;R;Cwn%Ncn_Ytx+*0~-|F;LQ&)z7U(u2CPtJX|8r3hpC(`}eFn?1lvhc#`L3m-WU`1R?W#o*mblA8_yq~v zlUb3Pm`iTG!Hl}pBS#oNXQUH#l3_UTrJ&<}Q}Dg8t5AZ*o~xIasWA&!$%#WXO?i!& zT#)pR5uwvSt75#0-tRqLV|$?Rj6A9VO-W}8p@sZr2VMpSqdF>Qt#*lfRQ0?PcS7A{ zcIN3xDKHacz_aQq=SrqdUT23i{L|1y{QGKp57bxz4J9qNN$xbuc`@!~Af|FFHA4}J zj5}Ut_kHPhLQAZF!v)a$BiRK(!3b#ZiSd7>gh=F6+LnGtl1O~^`ZG? z`7tAah}(h{-h$bThqfr&bX;D34a#YoER{c>gOqCvQgWf+8y>-v zSOh+n2PxVMQtZH%V!_=I(JMQ>&aAoG?M+K0oQ$=ADETLFGN*!P0%7ip36oA2(DSzc zq32_8uBc#!=q3B1s7;<&CQIHwZh|SN+}(mnNUXhse+%FzP3lH!xhCkKdUor}KN`TP zgg*8&>FkLK1J{?bE1}qtiTNPhAGxIHO3oZ=BA57&18g#t5ufI1Q)BHSC~rc~N%uQr zdV5#R;s83#=Ku!9w62}ykyTwffYY@(5C2>XDmc1;0dLqF_@7qGfaIzSXv8+?zEobEEoI;&Ucd9<#g7e^%ou3$J*Qv!v{b?^V=X6O)60mURu~6IfUhF^9^=oF)Ji1 zoLm*=x1fjX=L8~XJGi=}Sr)KQ@cr zjlKm?`>xJcfPVEhb|!1qN8sQul!mqHb&nklMF@|CfBE>HC4@@eOf#gSKEHIYB?fQp zJc;^XS5q?)guV_@36HKe+S?f+1G;|Jh$$~9n3u^2C^g%>0Iw-?h0?;9J z)mu&M=#*up0a)+sZuQlxbW za~md1+~lES7W0L126poNn|VC6kAY^FQoCBpB3?<7N}*LWaMr3q9aW5T!1R82unan2 zdEmNRsFAh%R15JI-rA7A_&`cB3yAbt%_(5Bs~>JAodwS~kWAoK0E?I`AbMKXy{Ff_ zDxrJ>NeoTHB@%ti#Hl=D0Sw8td6uh3Od#e+8Ui%%MZ>%B$f03yrdh{{qEWfO|BuJD_2ug{Pe8=aM>c1-784J7 zL>^&?zGH|=6&m_t+n}K}X!fS*BFWu#q)-uxgbFKEN2}7SkzY0>h~`0f6D}KNan(`j zb;)@v(874kgKJ1tE^oM${y+!9dJA^$WBhzWktZakPHsm8Ln$#5zB#Z(yC|m5(i*}= z_sh_e-N;F`iDjqU3;I5H-~fi5)#J36(&ihbg%y}bWEdlyFQiB`K$JT9MSj?eu$#y6 zyduFW0j&znSG$PGrgZW(_^_$*UnLV$ z4?@Fp3V)K%Py?(dn*8;6IiaP`z5lWVYa?Lf0wRdrC_nVd2+p68^ZE}Ll6#El{f$J@ zdxe_%vVB$61sa{*=|H*GOJ4Wsk=zRs?`siB$t!E>=VnC$(MkqrjN0XArS#!g7!c|c>zu?08Q9Y? zMd&ux)MqBJV>sw57VN~0Y~*8tjTtJ1(J(i4R=uba5s3ef@7>d!CC{Ado99 z&#KNN*C^+HXG0=yRfCwMfE3K05PI_cK|9j>t>7%=kI)&#PZ-V+)qIe(?zjREPpvWX z-iM9tQV64BZo3JU(%t^Fp=lnmXj~?}f=&n(N`z-X4|p|f#|{xF>5>DfC~B~lQScEz z%WqsV<%lJKdOKCzZyR&AIRlc+#>YEr|iU?@&(dv(%4#DGH-#CGajX?iqj0)c;i3WbTM3rwXCrhly zJ)D#Pr*aqFmd;{A&Adwf3i|32&qqC5)cE%eWGW&Bjzitnt+#p7Nw)1RpW8j}N`fQ* zTXV126RS6n1JU6#*+~hX+*C?m!CiHK$gWZ|CT|aDmW2ou`>r)x7_6H3Y+Fk+XwS?G zf{;3|!cHnD)hB^1{R;Ih;*F=+a=W{YCc=BcLL-D0WdgB}?B2s~!dxOXZ>o?QzM1%7 zTU&PR5uszy6^ucr8Nd}d0&uBA1pLeEo3>9WgoLZ}heped4EmtWKc+1ehWFIVXOJ;| z!j1~jm5Y&-U3NT`;~_a>v||+~dReWW4CSgTq@o5?7o8c4^g_r`F4*)+emNFKEQ(QY zmIPR}PwQ}06p~tw}Kf}G5LOux&4Pa`PoU; zK@YW@zRc1V<>S1sTQCg$z}M;Dc4}CucZ7D0N1UU;jYiFNPq=2^3D{kW2%hb_BMzJ)Gpn}PG9_4(B+;IlNsm3eOOf}J{3l1t zA}J5St1FPi7=W_xJ@ByYROQfq`v|XNtf9@>qR$r^hd%uTrd(0~Ctz*YUhv&5RB;#5 zAzV&`YEGT6!a;rQAhg-3HzLq%!N8JL?1^95A(fK!KD#rrqUW}?xp|?1x$Rp}w5&EX z0esb9DNb_FR5Z$pi}`<^0aZR@VQ|xQ@3j!W@sazcrd}(at+H!4(YPds7j31Uk~uII z&4Vv4y5nve?gs`v4uoz>?Q%7%GFP5D;p()%b121Dx%gG6QVE=AHUTA(`&BuqDfHD- z!rtRkklV0wQ*2!xR6l!vZTe}#{|7l zkkrXP5y7N3e3CKIV_U1Q>+;tBGI-#=B?DLCdkhT-b8L1>d>GMS=uoE;A{e%<)e3&7 z@3aowTuys~(+1qlx!b792YR@Sv=ct;N@w%%i@a;tw!+Az;-cc8DOvpzKdM zDRI-gMq_Tt^CvBDP{_aMf*ybivRCp7(%_-aa!YkrznC*25q^-bO-T8M6G^`zHTAh> zRpW8R#|;J!b*9_XrzQfF245yG0lt@9UUwL7H94vDFd2yzBt6-R!X#mR+|ao=UKk|G zb$Co-!2*}5UDDDYit@&2zLOCu^sFSI)wJgeYcq&LS=J3)8Oo8vz?ZwI84tEHqkR-Y z4y*ISO1b?;a}^TK!qE`EU>khbTa(PErQYSeG8IKhLg~h-3av&c>Q1KJ8iCup^AP{E zs2Sx|$CQNDQrl*_>iH_pGxh1)x+93=P;3R`q9h?Lj5#{JwL4n6m8+?uG29C{3F%jh z@Hz`FH+4QeL4tK!N>pn6HolbqR4f3UiOuTvRRJLVT zeAi)fBw`=vtn2smRCpVXOh5!**c0bZ%kj}Xl6bE=zt2(AL+O7z5J2@f^;zSN<;K;& zeT+J&&X>onPin_ItVFS8(#j( z>`bBG{w<+ID#O7t^p6iD>q=-!wK_F_#ocN@kk^+lO{T_wUAOsqAd0B9CEM^xrB};q zPmof2X%F0uTERy6O;4P~+3V=@)tO;1MDNn+ z$0xa@c4Z_%EBh!;1?7;ow_S?BFMF#&&p?mDNFT~4&7FHBHl$Yy&8dE z|Kd|F)4J5FqgqzWuX-rj-9!%>){pT158QfI0m~dQ{C?1GTg2l!pQe!y*;4Dp-vAHD zmM7q6-UW_Th6wzsBVMP-tq8FNMpynzGgEaK^z!BcPUu8pYU#yM z=o#amApjB#(J4L-Gg_}eT#aCazg5!g;_Hwy94#kVI>!BJq(P9;hIhudZsw#m{>UD3 z9R5U8o@}CZSxqn1p~ZW*8!fE~J=y0D>U;=juiQly#UAb$@6Lnt(Y99cYkN*x9w6C1 z?coT1&Q+|tbb~3aeO0DU1J#CqWQUwp=X8AX;p;mSfv5 zStC&a>U_mL9}@B?AzDx!?w!3dE(a_=LIj5Eb7e)A48z@Myd>e{Hm=(-q5*(F>5!%c5P}2j z2q;#lb3CQe*ey9A$Tz;O(jj8fp}MmDsf#BID}iM-kdq|RPo_uYoQOgVd+M~u5 z37J-g;@%z&C(c|=b}AFU5ne`24V}!3%uqt)GygD@&iuo?K41KSxGfp23P@(?=y+Xbc)(Z!RPkpD#4BP?+B_dGhjPj}{?{CsT9^Y< zJsIJ)jHBZF&^yu7=& zM4zDlwUsa3(bz%XOpTmQt`wUyMB`JU@yJJzJrv)XhPhA^wUT>xf=A7s_zn=(yB7xf ya3*|U@$sTs7U8hy28-;l$cq2hqrr^4=*S(lcUyh(;J#KfIyUz6jcV_&%nQ3*iYbVNbqA1`1S#)EFlb0 zHHm)={$pVZkTR2#gP;b}un^E6K0!eJg+M@pFKGXwKY;0P|Ct_Y2?6~N3s`{~&asDIPDe}UHo^)X<$gQY6K86YRiZESB#Z)jp~WJ>RD>+lxVpD~pQ%iyi!rkHo^+*@2sZ!OhK$-i?Lc-pQPSiHnPifsvVknVAlZpaXi?IUBmu z*#SxaDda!oh?)Y8oh%)kE$!`y{>n8pvUhRjBO&>#=-;1z+Uaa*_Me*Ufd9%CID-s- zpD-}dGcx?I*ua@pwlueJ2L9X1|HkWX=cxg3()j$(m%3kV`9bt z*6>g5|8UPgt>*n}6Ss)Ht%H*(5D3m4KNIgi?EG(O|C!5w;+0K-_BJkmouOuD>CDgk zFP8t2{6D!AoGeYj-u=t=Z!P~d?SJAGE$p4`!6ofvX)I;uZ0ZCy@n78kq40l?_%E{l z?O1LNQzI3y1XEkE8T@~%0`OmT!Pw9a=xlFn?eJG4{okUpu{1Wd1DY~$F|ji-ae?ax z?_c-*vw;4)od2TfueZ5n|G{bRq^2zUf6!s;0<<)ybFeY=u(1R>)47@&JKHaaZ>H~)MGoLE-ofJ#sc%Wev3S|0F#^JA<$2S+d>^=2;^+M|8vR`dh zww$dlQ+$2g?;G!$*3}*ND=~7J?E86QsEW{0g58!uNz?@-KVSi{-wYdxzd?Q?{t?7h zQm3jaCJ0wYdD7i478d4fy3l-rf1O_6O(PF5fD)w68DMBL%3&L3|nwFMC z_@Sw<`jHr*fPsP3GGc1bNi{2dl(;M^Iz@^c0S$;4pP2I!-aVR52FM>gx90 zqtfxikKTRJG`cyl8_vUTEt;Y*k$-qMBhg$toBcFBzjJt`QD`FHiO1_JMn*5bKw079 z)}EG9);yGk*8U=a@#T*+8H5WRgCVd|;#EjEl+=0Skx7{PZJS(EANk(i(Kfa}*jdHT ziCNhbD)69&u)t25>|!v1b7=gYZod25_Z98rD^-Qwe8AfV|KqD3JdIMF`ny|>mG)Oq zdUI0xI?R+g^YF)B&i51RX_ZEl>hsfqQ<$eqVRQU9MEk+EuInzxlDdy=UNB0UI86;@ zl4nKfXWM38>E;hqW^ccxm(qv4H#U`Ub?HT78QH8Ru3b3O9EkQ2dI+rqdvOL&`K0zz zvqECMk5{oP?0RKjR^we-q(G3)Mrc!u`9ay$Yyx9b*$U=y3h^yegmspL*Ow%Tu0%K! zJ?Ec)HVTCIM2NMVMQ#e)oiB6FFCce~1+wBhJigw5J`@IJ?}zYQ*ymzB#6!t958(zP z{P_br>rng6|$}6hmzq4td1qJhVsHKZKZ}b)gWjCt{v?0q|V|!4B+GeTN z$I#Zbet~@B75cm-pd4LYUaM&3M{T})5MDDP>>HT>%p8)?vA+PsqFa7t< zn*;luL;W@!9)0gG#q?H!`m~moM&_Ux9#=p{rhjxO-&o-us|)@jpqHCmIK(75q`~Le z6#)@3xh$3Gfy!_wsAvxvZIQ+>@b2!eq_mW4o1vX{U4Bvr_roWd$7{zkkLwR>iSj$W zr*^`Ik@E3&1RYU8LnHV<#|>VKj)znxYd9UlwX+S(pN#RBa^GI&Ic zo-~Vvis7v>>AK4mc*Bab?AmuTPOofyk(e|fVA{M;Y|46J-jCZ_UJ0uuhVpCydg#JY z=fq>Fk2)8txH15b-G{q7!+{8lme>1L;)5%b2sBq_iy0I0_!oS6uERB;!*(#1e0WXD zZhwz% z_R6C0v1(_=gHO5-v7&-c70h?GyMxhyHdi{M+NEKrqDQ%L+fww$|df)R)29v{=wDEFFW z^2A^ZL&r+6LOR;k1iFSUQSO?2QpOdASeoQd=z31gtO+S{lyf0R3x{6qMXke(G(ulg?Cb^ferCeM#l2iI zj@<@n+YhK|=$fLcAE=F*B{sFxMZ6Qljt>kSZ+?W{+h1B)iO96?Tz0ybgP|wor1*el zc_L!9QN!V<;v@8OywSFOv$!4b;Da#bhCp%-zr9dJoaNFZwsiTM&i(G8OL%xn391uf z$63!br1${Cgs(!oSmYL`tq5Eyz2PIPYim*V-)}M>C*3-Y(^XwlAc@c2MUcx3DHjK! z7bVF83>YmuA}HPN_hOMkdnLuuh80&wdB1Xq;AntUcS`kNu;n5#f9_YvEn&!A!VtbS zR3rMn^>m5z1XADgK9hxdVb<7w`Avn(HrBGwYrBVv{z;lU6S4T>?ZB1P+E>2LWt96VSkUhD$k7l@Kmo`Ps-C@z~ z?W6C5eX((THQIV90$LV!P4rB}#p7P|I+?d>E=Wes%WDMc7*@{t&MWmzQ`^kDQk111I84TWt;q7=* z8J+7=NH8Ad4$GAGy$YR=mO=IMs#i>e4z%GYF-V%nLlW<8FN!NzGz)W5xj zyPJ}-$f{($tM3m`th_L~o}Lgbsd8Vxzc z)K=rw<{P+D{mWchdJ%o5#)}Wirl?_IEyd=3t<%e+I2g$RF+RE4_9VK!!lVShN+LP+ z3cBzi4Q6rPoTnNO;BAC`&Grc!Oq47{{|MZ`J!8UCAg@@yuUME8^*@)LE`(?lqdH6w?1)tBn+-@B5`9!m0nzJ zmm3ua;!1>f1TijRzumgA00Q3eWxn+L^O8Fgl*s#^sm3kYInwRh9U6vMjTMx#%yUfS z9R_oeXrNo%tk7#7@+}e(NT;l(7$J-*3p|4N?dBTV&7s?pD5`rH2MZKV+quFLO&46( z+gswkFJ+jPg~-+t7T96gXrOLsmG}?2L)O6z6e>y;+Kt%R416Jcv74d6&dg#z9S?0CP1`qo{I%o^bw&aqVE1dIAkM>@K;p7MQ zBXsbwJThn$>9%XO(aTjf2s>{)zOZiIDA5R+w+_E_tshWM6u6<}tf%@FeF;yzS;K)& zKIeUtg-r!hM$nL4WB&bQ3gaqgq9Udry^pa8+MWew&URV(Vg@K%yQa2>P7n`C(V|H( z@Qmia?4|(mi#b@+0BjYg(JH~bxF47t)1O#R58bU%vif4oKD{;bzcLE*c`2a|lb*X8 z_zhKf^--8<-D>6~>(RsS6he(kQvq+q#=gg*HJz19exwcerhlqsw^-`G8BSC*d(gUERp4262Gfx< z4fsGIVsNexhU!3XNXFip>yni4zCzI>H6L9wtBqE|KjsAF>Ntd66VR1>1U zrh}y&W>G9a_eT5Oj*H@SM;2eRFR;LcWmo_k_D6j^x~=UwXgW5|J#6llI<-Qus*HdM z>8v3AOs>k(h$*GUH7z6jN9H$R>o%Q9a;3qFQ&KXED;d@o%De7?DM<~OvZVo+_~8V9 zlA0el%Lc)X^AaJi02O$`k#Ul_!?P?ov@d#gh@-NqGBUPP{>fSW$|eML9o4rul;1DH zMh^Q@Q}b}N6+RoL*FzAPMj4hTngB!`gx&0F#d9N8h zqHFSt%v5HE;|wXZC5)8?;NbbyN0r;Zh>~ce~dg(sYd}(IK5y@)PCzLqRosNzU(3sM-g&d8h1YbxRc&P3? zKLygzCXl&F+zJOIp~`8};2B3)Uz)T!`3Ybfg?vuPwUt22%UDWeOQ~t%0xc{AGx+`) zbANx{w7;_q9-eJ(Y!ogXUGPbi5QL=}%kzG_$sGzr<_}9rNg2^MVK$dE2x1%L21ylq z<#{Bq3^IyZLd}Yk@kJT8K+$g2FC)xN4C4tp@uq7;kyi+=&&>EYcbwaTn7?}6pVdlg z*;Fmt>)wQwAj8cNTgzo;zH=f}VLqezV$WRE%Y{u*BxA(E=Jo&XsV zHXS)Uvy$?IU-7hf#LFL381(H>)j(eHZxwQYi41q6)m((=un@l8D3%!O#%^>PxoxX_ z&dScp!stkrSC&WpItnKW+h5by=;4KV+I2>mO`lVXMe2_KzB3!M<&k+W zA?(_(#BDgOp`NLN$##q|%cZ=H@S@xC%gf7aT~5`**jUafu0#h2*|RI9j-6FoD{D2; zSOI+lwUGF!(LI#U%j~lWLh(g4B4IWqt0REkh)>C;$g8WXjw9r$TPNk!ITjeFjzj)_ z00uOn+d#sXZj#@QIz|b_igZZU@?5n5!Wf;^y~bycCBZ(^ATF*4;RUrwJvf?@av&!FeFE&LOanp(8u zAcX5Mm9cgsGQ)jD>P%K#;!4&6^bWmJ4>hh1H26W`m7boSK7ys=4&&qU!|Z%(a$2Q2 zr8wt4iW)MU)bL|I*+f9stw~TBHP<^^2m)Q8!E|U~Y*!eB20AP|h$NfCYc!F06(608YdYH`xSzoj!NRFClu_V0vib zE<;`bKK+-O)hg?d{*48ZkXy$kZ%2O?%jrQFZFVw6*H$$78ColRx<`|dRbI%b-R3sTtg=`XM;8X ziF>fcW+(uckf7uB&_Y}Q5+NT&WohirXh6=?is?bkn0kl$0ZtG+ydP&Irm$m=)wplo zUK^_p30z@IaOxfNsFjoL1$EwWoq7K@Wc`FwH|nSrYGHctof>JF^F#0W5qVM#%jf0| zn_gJJiW=+LOeSaM8h)%x4a+J{q~Y?iefO_s{Se)7+D~;-Aw*5a=^O#(7p+i#9w9_f zOI2`Ww`&q&So#6<1{O-axLS@kx;Bq>Y z&f@w8gwmtY@w)k%eX(SuHazLss73}&`M%1VH(#Tj)=cWy^FDc-1`FoAF7nn#@1@}m zqu&Ch3loj2a8#N0YW)4*d>@z3FB$Dx5?Fv)XkaTetD}oiNNR^mf z0Yj1vYDefH-QCkfWt@{MzfN7e-{Et6r0hLuesNiszita`%^z@E>B=LG9B?Mf8|8Rt zBdv@EeMrBwtC<=Z-+D(^KlRLG7Wea6B$4AJfy=}Y85heQX-^rYmd`%zW7&MB-wg@0 z*b_w&P^*?zuc=dFtfVTHuDhNiImI?^GmR3hwJ0-;oSE*L5cCtJ|0Y+3D#OezwKj)) zl75w|M~Sp88K0NcF3QFP$X7g@+O7`y4qgPTnB`DF}Aw{e79qnlB=@3W?Duk;{X zI&-7j#YU?#rRg7hW-RqOPt~x8))nxY2PntRtnCjYQD;dtKLRE_%nLH{axMEa@Gd zT8El97x(F5c|LkqwMHOKn(PUWKD93cqc2hKM5l# zY|Szuh9nayN6xieQjJQ8BEt{ZaePSd!d;)%g|jefn#~*?d*C0pnYbA^4C@RAGaEwJ zvX-To;!-_{sa$&KK@M$r>;4#t6{7&8F$=F4MDlXpfp+pUXEv4&I~-C2MkQO-AuqAz zp`&8(s&^6`STb`dEQSbb8Z4w0ngTRApIHhDwoGo)QSM|y5R1=hElRp2*X{QRKN7|d z(5ij%5M+ENO(-UvYz6?93W6!Hdj^GiIJXxK#K`Yh%#J(la&0}O?PIhDa)BD^W!d) z2o#mZOyvHzarkios|TIUyrAqpHd?I-ki$>HIjP<-^(12*dJb>Bgz=sRp7Es3DHAi@ zuRad$KEqBkrGxv$2FJ6>4w4CW^o$q|UfXUhD1`XJ_7@OFBB*C8tx)0qA6kHp^C5L5 z)m46rSUYub{A5N-3CU%FM(f z2K@AZ!3m1#6+$tFmKE)F;VjREeL%x+)*xKW9u>{NFR7UcYFmOg%Ofvc1XUk3de*w+ zs(!FdIPytx&98@i)z0bb#Ci`4thN;*#VWD7#C~%D-rK>M5@vnSF%A7Waq+Lh;lsA57+4;1)jI98)R5Zp<2^YGb2@+fI88k+5_{26Iy{)VBy2!1p0 zDREM;ojHg-qrc4o*j=GN=Y{8yu6FNdIng962qk2X)XUy`#N5#)Y=|lMjTR^RD9u#hbYkn-UWhv^ctDIDMuFDsyKRQ)6T24bR@_d9y?@VS+Dydd>L%Qls{n(Kh|GMV_$;naz*(v?Y zS9y~Zlw7jJRCt_EFwdp0IyzjVg>tKd1Ttt+lx1aBimQr|g1UV2{O=PbRsaN6IuY{~ z|G*jAk)u8$0b~;$3(jXFowYj5hmEJHrM7pMs+iyVk?JY)KMoFMgd^G&3sx&V7Xp6n z{dIGW__*Q7RbBO;bLDK1Cw5&(+^7 zu3(Qw=R$MUli3-f?|X`Q=Ig?;Grwl%neQ_{UE9Z%Ur?_6eLXqd4%v8ps@8I@$nd9S zg~%wdD=jub()(&>pygr1Yq>gs!v(}lX`AT8J3?tK9NP&}9bcGPOt?s>Qyb;kxI#Kx zZAOO2q)jstXqr9(_KUUG87A0zT@WFGD!V1#j`6}iX4X_&hs|H+M`SdnZ>;^gg=kuT z0P+Gib+@`{sRQ)pgZp5A;isg_W-cX+crMpgQ$;E+_n=CBCzLLnL6T8DO}&h?gt}N)D)$lvehmNkA&BKgGHqY!6-K6^3Xmf*s9)NQrYz=C{-oR^$(24nvyar?+ zb{hbIBZ}T=Zt{%zawhQ}u{U|>aJ|D#HWxrDcO*M|jU-c@@nV9C+~j>tSgWtuzlSuN zgXpeX;`SUDg4{;XinXfe{mIvHVsp0vp1#*V23yBp+IavcY5QjPd{HkJi+ktD?47NF zD9YUk1<5nsbT_{`_!mBV3=l1RK-o?`o_rqR-I&&J06(RWdI z@>O9jB{L-Xt>ueH&Xpc3x-DV8esG1J)d2L6f;Nl1_a%$I;13USS62jLGQCZ21Q}f_ zeD4=j-rGKVLqnp_UoPdSIA?{WC#KUPc^sDL18=nCfiDycOg)=@dHE`-)j}{D;=b1) z29l;5)2y4kt|8)4!DnnfA5{Db+io6#J2BA?w)p~KaV-h_=44+@AimQMg?-XC^G3(H z@j+kl-=%amcJ`gO=Zm4(@3*8nK6eYD6NZjk_~o){BJ#P*MP z-+4YlWxFY3otTdzciN!&*rjqdiiD*8~hSZDgyuuJmNeXv$Okvx{i`eMT2$is)s z;2s9k;BwOLiICwQqM%!j<}ycFjytq#;O|f7=QWpt77HL~cLTxeB?i>EstMY@cjfv6 zw$1CV*k+cT_pa`TB?3h&5JjGE-yADUj*Je*WF+-CReXrUQe2f+5v6ly_5I=BPoUgA zhynpI#vM`U{B4CFwBI(f-5-ZG2XP{;E&7W}mZ{X3qZzZMJq)KD(ueC;3ix-{53uQX z!*0B5n^@Tm9(Es$fSi87_XD%`d0dfc6){BWe%TqwgUEp82qzGBMJ}j4)gI0=L&Aj9 z##fse%lyf zbr^V_Zu9j^zacUOVHXkbw=8%JkElfrvfEN-aV1Sv@WLw}ERt?1&C#b#)se|Ey+%uz z_#U%kOmWi;eHV&-$kTtN`0$Gbh4%)seGOC0kHuc63Odw$_Hp9t<{-5%E@E<{B-t#2 zk%0?yQF!8W*zp<8=7`H&IW(LpC)p;iQ~H%LLt`mV~Ahd57Z$*Byc^lNGq zq$c0SQ0v{O0r(FrNyp)X=<2MA7y}}Hw)rc7$OByK`dF$^g?R0!%BFMywe%%T!3P7h z?LkahoeqL*d~T^(ZG6Emjq7c-`@i4215R+sj-s6ATFG1;Hl*?$Xi&tCtj}|5zL7d$ z0zn(JDvPEQc`h|wzZ&vT+j6`Jpm<#KQ!?24P^3KUJVu7i(r1N1`4gS$SDkS1>_bSb zDK)@9l{5@Q#NAgZw1MQGu;R%UuVe`0G`|MUBf=5M*CIn&pPWh4x)1&x8GFM%EHu(sebfvQ0cS%endAbim^IVpKDqdf3W@EwX?U!J`)DY~JXf&FTA&OE?HK+sK3|UZZO1$2Rm<8~ zAqzTHZZF<(B|vA6baOt}!K~^>P&Q7M`7OO>0@Om|Js^AcEm)}X#xY(7DraANXetKmuGS=Qj8 zERZNiQ!2P6VX6nC1N|}Y@@y?%Qq{{O=&o7&;kqBc7daezLMEd5VciB_zC_& z19RFZ$&d{Zm@VTLgV7Pqp0Hv{81C|?T)7xtftWZzR*05af zD~I|(DvHp-HC`<^9<0;kR{{H)fQ&Kw^iBfDPP5&k3+uo|g=X4`-DP?L2IH)sB9cIY z3bs!)MRlfliZ@d=_qn#T6hL2N(rk*GxH-qOnT>_xma!{cmEO-CS%OHDz`J_=qhhzE z9t1Rc4)oI2qf*l-$Cc4yGN{~Ok`)gMnVg3)r<|(u*W^6%m2reOb4D?xcP$6{Tl3gq zt+*Qi#p_vDQW4Zt>mSuQ|0Ki3D2g3cFH1dTYyX%c-sdR07%ww2HBp=|Jd*tbFA5&% z0Ez2}DXAj4Um^Mg#)*vx1O_RhioKI)mvbK4;p8zAo~5OdT1Dt72(p(BXUQ=oHd*}> zk|=%7(u{A7m0raxm$S?LTo;lm<;>23^?=dGFU%cukz~&mI0p(&Ei@IfZ}Nj*ro;zU*I^yq$+^4}%@OK3N0cqix(k9c%_4F+ zpBoXfYx48Yb`K3OzCMsnh3eqFU+YOikTwG+m*&XIND>%JPcDwpk=M6Y{)BRFw^(oLKXnh};RA-eI zgUE|*w|JMKZ{%AQh5kIPYR$~GVhJ6ji<9o+7p22u;=@NEF>GUru*gGxJi!V?cy{591Sn{~fdID<|5F{U23p#TI4C#KSplQLS?EBR z6{EV(?|Z6AssTte-1_&)$zb6{X9nD`h$IZ~vcS0H!Q}Fi6nR#Oq9+_J)wD}=(DTjs zl^^6`cEOQSBP?z?4}*l?eYdC|i|lhGlG0Q|86X2iZ`Z%CCzp^aT_^DU^;ExEk|v!p zrg>QO^67;7Y&)_7xXR92-36gb#j)b~NpZCS-~4_5`SLpZJ)|C!gGescDFUuLn;^&e z@s&a~o13^|8*eOYKL~1a`ihD0%KF*Wct8Enc=_0TdwG&orN+rcrfN6QYBSiMPrEkY zSb>GCrXC@`HU{hcn0E@$D@|Yg`uq?`gSDlS`;=5@DkhUI4H$WO5AS-02Jdc!KmTr< z(wfHkpG@O>ro{j;sYTBJpL=*ohEoOEn! zGJG1rzF~e8s7jqZ3=US+J1hHoz)*~poGETHe+;izU+)UlnTb?91~b8gM6a%fVD;h= z&U+n3v9%~z27vjS|Lwf!O&I6>Y5z|-cr1L56FE@hdaebpscAgK9=^}fCZLg1Lr9lQ zd(h~(D_)`BwV~y?cSK528!AFvYJvoBeNwx>aOmi8BLbW2M36eYh06g4ldas?@>u;2 z^R`RFVW8QV*_!eq87FJhJId+^GnKl`jMl=~*em-+R-S|p?mbp~QGD;?Pq(!@kzjtc zW|8-irn0ILFLz>1tv~Qol)wWq9{5`<@{x1d8&{`#>Z5hFB_x-@Tbc(4X1tGEf$Ea0 zCMU&fPtDi7`KAmVx5_eOpvA>lcl<`e|7OC`_~ zIlXT4qMVIdas!RiG0rl@Lw;TD*uS9{>v&__D+Zf&Brk0&#@^Yt;^+17^FG!44vmbZ zYSo+8olQvtwp1_UQzcTA)HMfb2e{C;8$n34#W-)E*f&1cf_C*;2TIZ!EvsJ6+aZ{m z_fnXetkW0iI<|Ca4wngj+}PHebpRrbkJ>8f8u;we+uNJe!l)|lUV$BJPvHJXvKUIu zI*}~PpZheRABFT>*KQekWaT=fQ%sXzO5H7pqG{|NKkry`Y$yNbgq$x?dqcon+^c=f zYrDEd?urhMVzja;sXzEpbj-)U0U>@O5fnh*0Hk#{*M}VA=s?GMTQ{$Do9=P(G65|3 zuMnkHjXUpRap*^80I;aj7e`2y6ueze%-=N97Oe%!t(G9s#L?8L)rP5aR2iV4_Ux&4 zoHHzNB&1NDI9bL8wMQpf|7){!yN^&G_YgS(Q-sg zTKj3eC`f%@3kYRZTot^qNH&Njy%wKqudb1I|Gcq2CE9rgiRf%20ltiGHQ@=wJpKO4 zS;`*d4`^ph5(DxJ*nGx9MqPg3A(?o28I$atoGQb8FO7twkvQNSq#h7DjPKv|To$lB zB^0FA3G8~!-Ry(^^XUwG&jH@p-RBRqmK9V9aPYEwsw))hq62=SRH#AKfsk+Fn)!;+ zmnoSZtrtIL``57Y2=!<}lwd4O$LW5Li~fzU}On?ah= z@aJZv$|+>aJ5Tdg_kqAxL6PSqQ3OE5;b(4-C&a5cG)gkTK)Y+KOR%qC*R<<86 z+s>k=&F&BXuRi#zr#Av<>yxxb#=eo?a9PSzYLF`rTgz?VBlxEHqDAcqg`Ek4kEL80 z>A5ZnVRC|!{V>YA#$JZb=t+ecfN?V4t9XHYpsWY>AoUK^z)qt3Tk%pRE{CK&c)yH> z^s%6q-Y;(#0NkpII6E&ib6~fz(IFCBfE@fMF;A=XI2?+B393!g}<~RI!$p@xsh94xQZ{TzX6X4LAPg3k6%VaPr)QMz5b6K4dvsa$X(F|ir z40`mB&;~Mn{UyHe_^UW zG*;@JjMpNpt{o$dnQpOp-C1aa#9ns8n0VB3!yTJ!gDuwe#=+I7+`S+`5KRQBa;EE& z;sn+UQ*)=2DdD#CW@Y+l5!N%-Mal>y-Nx6$PM4}mT^D&h)&6t-LpCro@8a)eTzZ*#Ac$@So5(s z=RuuT#|yVCwNfxdMh&T;Rh~PwGD$4$n37~0JFN#*4>?;>DCWNkHN>CcR)od4AaP-VXi)(nTMM+%p>5^$z#|72#=dm8A78fBcO~(nHGvFhcNqr zElkoEYc{ID%InT_&x;%N00re$1{Ma}O6o9qY=ECBkRwZnkvnJ0Nu!~-BMM_udEoHK zf?FM2_M(z(XOg^8udcMc1g{3{niklJ18A6lqxFdU!cThz52}+RY$nSRrUFgoaeXYT zk>^Lny|Val8F5Le7e1D zzMtXR(>3=j`1}<|vBJI`7DHK&b4!37F8{X*{{Hw+x%|?D){MtthH&2+F@W_@D!kYc$mLAg;{2iqn8oe1>z`1YDD3eGx zN#T1b_Y_@&%!cHbLc@AQC#;`~Qj4O0ilKh<7mO*YO6=nl1_h|orq$o)4S;O?OUjsR zZHjJG;CQl+aJ_A@>Mvw!8xPzuD+>LO@4i-l%N`Oj-|3<Nc;=c*GFe0GHQN4zCk z=D7u8qH^wdq=^yVg8pvtG5y`*Ln!{^r5az{>@A3G&spqUkcA|bR5Ry)LaQ_P+gkn= z)O2j^o6?!jC#&+b2zQokLhEqMfBC|Ka=3}E@PqD{I6|-$9P2{2n4#4A#UBkE)gt4U z-}c4d2^> { +export default async function createPlugin( + env: PluginEnvironment, +): Promise { return await createRouter({ - database, - identity: IdentityClient.create({ - discovery, - issuer: await discovery.getExternalBaseUrl('auth'), - }), - logger, - permissions, + database: env.database, + discovery: env.discovery, + identity: env.identity, + logger: env.logger, + permissions: env.permissions, }); } diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 20e14312bb..99d18b9b12 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -16,7 +16,6 @@ import { CardHeaderProps } from '@material-ui/core/CardHeader'; import { Column } from '@material-table/core'; import { ComponentClass } from 'react'; import { ComponentProps } from 'react'; -import { ComponentType } from 'react'; import { default as CSS_2 } from 'csstype'; import { CSSProperties } from 'react'; import { ElementType } from 'react'; @@ -53,16 +52,6 @@ import { Theme } from '@material-ui/core/styles'; import { TooltipProps } from '@material-ui/core/Tooltip'; import { WithStyles } from '@material-ui/core/styles'; -// @public (undocumented) -export type ActionItemProps = { - label?: ListItemTextProps['primary']; - secondaryLabel?: ListItemTextProps['secondary']; - icon?: ReactElement; - disabled?: boolean; - onClick?: (event: React_2.MouseEvent) => void; - WrapperComponent?: ComponentType; -}; - // @public (undocumented) export function AlertDisplay(props: AlertDisplayProps): JSX.Element | null; @@ -448,9 +437,18 @@ export function Header(props: PropsWithChildren): JSX.Element; // @public (undocumented) export function HeaderActionMenu(props: HeaderActionMenuProps): JSX.Element; +// @public (undocumented) +export type HeaderActionMenuItem = { + label?: ListItemTextProps['primary']; + secondaryLabel?: ListItemTextProps['secondary']; + icon?: ReactElement; + disabled?: boolean; + onClick?: (event: React_2.MouseEvent) => void; +}; + // @public (undocumented) export type HeaderActionMenuProps = { - actionItems: ActionItemProps[]; + actionItems: HeaderActionMenuItem[]; }; // @public (undocumented) @@ -1357,7 +1355,7 @@ export function Table(props: TableProps): JSX.Element; // @public (undocumented) export namespace Table { var // (undocumented) - tableIcons: Readonly; + icons: Readonly; } // Warning: (ae-missing-release-tag) "TableClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index b04c247b2f..49538b680a 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -523,4 +523,4 @@ export function Table(props: TableProps) { ); } -Table.tableIcons = Object.freeze(tableIcons); +Table.icons = Object.freeze(tableIcons); diff --git a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.test.tsx b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.test.tsx index 3337571d4e..92ce241aa8 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.test.tsx +++ b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.test.tsx @@ -60,7 +60,7 @@ describe('', () => { ); }); - it('Test wrapper, and secondary label', async () => { + it('Secondary label', async () => { const onClickFunction = jest.fn(); const rendered = await renderInTestApp( ', () => { { label: 'Some label', secondaryLabel: 'Secondary label', - WrapperComponent: ({ children }) => ( - - ), + onClick: onClickFunction, }, ]} />, diff --git a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx index 125363fe0a..e164244ea7 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx +++ b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { Fragment, ReactElement, ComponentType } from 'react'; +import React, { Fragment, ReactElement } from 'react'; import IconButton from '@material-ui/core/IconButton'; import List from '@material-ui/core/List'; import ListItem from '@material-ui/core/ListItem'; @@ -28,13 +28,12 @@ import MoreVert from '@material-ui/icons/MoreVert'; /** * @public */ -export type ActionItemProps = { +export type HeaderActionMenuItem = { label?: ListItemTextProps['primary']; secondaryLabel?: ListItemTextProps['secondary']; icon?: ReactElement; disabled?: boolean; - onClick?: (event: React.MouseEvent) => void; - WrapperComponent?: ComponentType; + onClick?: (event: React.MouseEvent) => void; }; const ActionItem = ({ @@ -43,10 +42,9 @@ const ActionItem = ({ icon, disabled = false, onClick, - WrapperComponent = React.Fragment, -}: ActionItemProps) => { +}: HeaderActionMenuItem) => { return ( - + {icon}} - + ); }; @@ -68,7 +66,7 @@ const ActionItem = ({ * @public */ export type HeaderActionMenuProps = { - actionItems: ActionItemProps[]; + actionItems: HeaderActionMenuItem[]; }; /** diff --git a/packages/core-components/src/layout/HeaderActionMenu/index.ts b/packages/core-components/src/layout/HeaderActionMenu/index.ts index 6fa74d9d09..4fd9552fa7 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/index.ts +++ b/packages/core-components/src/layout/HeaderActionMenu/index.ts @@ -16,6 +16,6 @@ export { HeaderActionMenu } from './HeaderActionMenu'; export type { - ActionItemProps, + HeaderActionMenuItem, HeaderActionMenuProps, } from './HeaderActionMenu'; diff --git a/plugins/playlist-backend/README.md b/plugins/playlist-backend/README.md index 75e0281a08..14a39ca741 100644 --- a/plugins/playlist-backend/README.md +++ b/plugins/playlist-backend/README.md @@ -21,20 +21,15 @@ import { createRouter } from '@backstage/plugin-playlist-backend'; import { Router } from 'express'; import { PluginEnvironment } from '../types'; -export default async function createPlugin({ - database, - discovery, - logger, - permissions, -}: PluginEnvironment): Promise { +export default async function createPlugin( + env: PluginEnvironment, +): Promise { return await createRouter({ - database, - identity: IdentityClient.create({ - discovery, - issuer: await discovery.getExternalBaseUrl('auth'), - }), - logger, - permissions, + database: env.database, + discovery: env.discovery, + identity: env.identity, + logger: env.logger, + permissions: env.permissions, }); } ``` diff --git a/plugins/playlist-backend/api-report.md b/plugins/playlist-backend/api-report.md index 5c86b6ae45..c7109efbfb 100644 --- a/plugins/playlist-backend/api-report.md +++ b/plugins/playlist-backend/api-report.md @@ -7,7 +7,7 @@ import { BackstageIdentityResponse } from '@backstage/plugin-auth-node'; import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; import { Conditions } from '@backstage/plugin-permission-node'; import express from 'express'; -import { IdentityClient } from '@backstage/plugin-auth-node'; +import { IdentityApi } from '@backstage/plugin-auth-node'; import { Logger } from 'winston'; import { Permission } from '@backstage/plugin-permission-common'; import { PermissionCondition } from '@backstage/plugin-permission-common'; @@ -17,6 +17,7 @@ import { PermissionPolicy } from '@backstage/plugin-permission-node'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; +import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PolicyDecision } from '@backstage/plugin-permission-common'; import { PolicyQuery } from '@backstage/plugin-permission-node'; import { ResourcePermission } from '@backstage/plugin-permission-common'; @@ -84,7 +85,9 @@ export interface RouterOptions { // (undocumented) database: PluginDatabaseManager; // (undocumented) - identity: IdentityClient; + discovery: PluginEndpointDiscovery; + // (undocumented) + identity: IdentityApi; // (undocumented) logger: Logger; // (undocumented) diff --git a/plugins/playlist-backend/migrations/20220701011329_init.js b/plugins/playlist-backend/migrations/20220701011329_init.js index 17a71e8438..be08363dec 100644 --- a/plugins/playlist-backend/migrations/20220701011329_init.js +++ b/plugins/playlist-backend/migrations/20220701011329_init.js @@ -37,7 +37,9 @@ exports.up = async function up(knex) { .onDelete('CASCADE') .comment('The id of the playlist this entity belongs to'); table.string('entity_ref').notNullable().comment('A entity ref'); - table.unique(['playlist_id', 'entity_ref']); + table.unique(['playlist_id', 'entity_ref'], { + indexName: 'playlist_entity_composite_index', + }); }); await knex.schema.createTable('followers', table => { @@ -49,7 +51,9 @@ exports.up = async function up(knex) { .onDelete('CASCADE') .comment('The id of the playlist being followed'); table.string('user_ref').notNullable().comment('A user entity ref'); - table.unique(['playlist_id', 'user_ref']); + table.unique(['playlist_id', 'user_ref'], { + indexName: 'playlist_follower_composite_index', + }); }); }; diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index bbea8163fb..b760611548 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -22,13 +22,15 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.2", - "@backstage/backend-test-utils": "^0.1.28-next.2", - "@backstage/config": "^1.0.1", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.2", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-node": "^0.6.5-next.2", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/backend-test-utils": "^0.1.28-next.3", + "@backstage/catalog-client": "1.1.0-next.2", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/config": "^1.0.2-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-node": "^0.6.5-next.3", "@backstage/plugin-playlist-common": "^0.0.0", "@types/express": "*", "express": "^4.17.1", @@ -40,7 +42,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", + "@backstage/cli": "^0.19.0-next.3", "@types/supertest": "^2.0.8", "msw": "^0.47.0", "supertest": "^6.1.3" diff --git a/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts b/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts index bff14b2a58..a746286136 100644 --- a/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts +++ b/plugins/playlist-backend/src/service/ListPlaylistsFilter.ts @@ -73,7 +73,7 @@ export function parseListPlaylistsFilterString( return undefined; } - const filtersByKey: Record = {}; + const filtersByKey = new Map(); for (const statement of statements) { const equalsIndex = statement.indexOf('='); @@ -89,13 +89,12 @@ export function parseListPlaylistsFilterString( ); } - const f = - key in filtersByKey - ? filtersByKey[key] - : (filtersByKey[key] = { key, values: [] }); + const f = filtersByKey.has(key) + ? filtersByKey.get(key) + : filtersByKey.set(key, { key, values: [] }).get(key); - f.values.push(value); + f!.values.push(value); } - return Object.values(filtersByKey); + return [...filtersByKey.values()]; } diff --git a/plugins/playlist-backend/src/service/router.test.ts b/plugins/playlist-backend/src/service/router.test.ts index 06185acae8..3f90a8b8af 100644 --- a/plugins/playlist-backend/src/service/router.test.ts +++ b/plugins/playlist-backend/src/service/router.test.ts @@ -14,9 +14,13 @@ * limitations under the License. */ -import { DatabaseManager, getVoidLogger } from '@backstage/backend-common'; +import { + DatabaseManager, + getVoidLogger, + PluginEndpointDiscovery, +} from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { IdentityClient } from '@backstage/plugin-auth-node'; +import { IdentityApi } from '@backstage/plugin-auth-node'; import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { permissions } from '@backstage/plugin-playlist-common'; import express from 'express'; @@ -24,8 +28,39 @@ import request from 'supertest'; import { createRouter } from './router'; +const sampleEntities = [ + { + kind: 'system', + metadata: { + namespace: 'default', + name: 'test-ent-system', + title: 'Test Ent', + description: 'test ent description', + }, + }, + { + kind: 'component', + metadata: { + namespace: 'default', + name: 'test-ent', + title: 'Test Ent 2', + description: 'test ent description 2', + }, + spec: { + type: 'library', + }, + }, +]; +const mockGetEntties = jest + .fn() + .mockImplementation(async () => ({ items: sampleEntities })); +jest.mock('@backstage/catalog-client', () => ({ + CatalogClient: jest + .fn() + .mockImplementation(() => ({ getEntities: mockGetEntties })), +})); + jest.mock('@backstage/plugin-auth-node', () => ({ - ...jest.requireActual('@backstage/plugin-auth-node'), getBearerTokenFromAuthorizationHeader: () => 'token', })); @@ -99,14 +134,20 @@ describe('createRouter', () => { userEntityRef: 'user:default/me', }; const mockIdentityClient = { - authenticate: jest + getIdentity: jest .fn() .mockImplementation(async () => ({ identity: mockUser })), - } as unknown as IdentityClient; + } as unknown as IdentityApi; + + const discovery: jest.Mocked = { + getBaseUrl: jest.fn(), + getExternalBaseUrl: jest.fn(), + }; beforeEach(async () => { const router = await createRouter({ database: createDatabase(), + discovery, identity: mockIdentityClient, logger: getVoidLogger(), permissions: mockPermissionEvaluator, @@ -398,6 +439,7 @@ describe('createRouter', () => { { token: 'token' }, ); expect(mockDbHandler.getPlaylistEntities).not.toHaveBeenCalled(); + expect(mockGetEntties).not.toHaveBeenCalled(); expect(response.status).toEqual(403); }); @@ -406,8 +448,25 @@ describe('createRouter', () => { expect(mockDbHandler.getPlaylistEntities).toHaveBeenCalledWith( 'playlist-id', ); + expect(mockGetEntties).toHaveBeenCalledWith( + { + filter: [ + { + kind: 'component', + 'metadata.namespace': 'default', + 'metadata.name': 'test-ent', + }, + { + kind: 'system', + 'metadata.namespace': 'default', + 'metadata.name': 'test-ent-system', + }, + ], + }, + { token: 'token' }, + ); expect(response.status).toEqual(200); - expect(response.body).toEqual(mockEntities); + expect(response.body).toEqual(sampleEntities); }); }); diff --git a/plugins/playlist-backend/src/service/router.ts b/plugins/playlist-backend/src/service/router.ts index 7ca41c0ac1..bf0b789b7a 100644 --- a/plugins/playlist-backend/src/service/router.ts +++ b/plugins/playlist-backend/src/service/router.ts @@ -14,11 +14,17 @@ * limitations under the License. */ -import { errorHandler, PluginDatabaseManager } from '@backstage/backend-common'; +import { + errorHandler, + PluginDatabaseManager, + PluginEndpointDiscovery, +} from '@backstage/backend-common'; +import { CatalogClient } from '@backstage/catalog-client'; +import { parseEntityRef } from '@backstage/catalog-model'; import { NotAllowedError } from '@backstage/errors'; import { getBearerTokenFromAuthorizationHeader, - IdentityClient, + IdentityApi, } from '@backstage/plugin-auth-node'; import { AuthorizePermissionRequest, @@ -44,7 +50,8 @@ import { parseListPlaylistsFilterParams } from './ListPlaylistsFilter'; */ export interface RouterOptions { database: PluginDatabaseManager; - identity: IdentityClient; + discovery: PluginEndpointDiscovery; + identity: IdentityApi; logger: Logger; permissions: PermissionEvaluator; } @@ -57,6 +64,7 @@ export async function createRouter( ): Promise { const { database, + discovery, identity, logger, permissions: permissionEvaluator, @@ -64,19 +72,23 @@ export async function createRouter( logger.info('Initializing Playlist backend'); + const catalogClient = new CatalogClient({ discoveryApi: discovery }); const db = await database.getClient(); const dbHandler = await DatabaseHandler.create({ database: db }); const evaluateRequestPermission = async ( - req: express.Request, + request: express.Request, permission: AuthorizePermissionRequest | QueryPermissionRequest, conditional: boolean = false, ) => { const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), + request.header('authorization'), ); - const user = await identity.authenticate(token); + const user = await identity.getIdentity({ request }); + if (!user) { + throw new NotAllowedError('Unauthorized'); + } const decision = conditional ? ( @@ -196,7 +208,36 @@ export async function createRouter( permission: permissions.playlistListRead, resourceRef: req.params.playlistId, }); - const entities = await dbHandler.getPlaylistEntities(req.params.playlistId); + + const entityRefs = await dbHandler.getPlaylistEntities( + req.params.playlistId, + ); + if (!entityRefs.length) { + res.json([]); + return; + } + + const filter = entityRefs.map(ref => { + const compoundRef = parseEntityRef(ref); + return { + kind: compoundRef.kind, + 'metadata.namespace': compoundRef.namespace, + 'metadata.name': compoundRef.name, + }; + }); + + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + // TODO(kuanpg): entities in this playlist that no longer exist in the catalog will be + // excluded from this response, we need a way to clean up these orphaned refs potentially + // via catalog events (https://github.com/backstage/backstage/issues/8219) + // + // Note: This will also enforce catalog permissions and will only return entities for which the current user has access to + const entities = (await catalogClient.getEntities({ filter }, { token })) + .items; + res.json(entities); }); diff --git a/plugins/playlist-backend/src/service/standaloneServer.ts b/plugins/playlist-backend/src/service/standaloneServer.ts index 46d6f7ad8d..3b6acfd09b 100644 --- a/plugins/playlist-backend/src/service/standaloneServer.ts +++ b/plugins/playlist-backend/src/service/standaloneServer.ts @@ -23,7 +23,7 @@ import { useHotMemoize, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; -import { IdentityClient } from '@backstage/plugin-auth-node'; +import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; import { Server } from 'http'; import { Logger } from 'winston'; @@ -53,7 +53,7 @@ export async function startStandaloneServer( return manager.forPlugin('playlist'); }); - const identity = IdentityClient.create({ + const identity = DefaultIdentityClient.create({ discovery, issuer: await discovery.getExternalBaseUrl('auth'), }); @@ -69,6 +69,7 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); const router = await createRouter({ database, + discovery, identity, logger, permissions, diff --git a/plugins/playlist-common/package.json b/plugins/playlist-common/package.json index 67a97b1237..b9e8637f17 100644 --- a/plugins/playlist-common/package.json +++ b/plugins/playlist-common/package.json @@ -23,10 +23,10 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/plugin-permission-common": "^0.6.4-next.1" + "@backstage/plugin-permission-common": "^0.6.4-next.2" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2" + "@backstage/cli": "^0.19.0-next.3" }, "files": [ "dist" diff --git a/plugins/playlist/api-report.md b/plugins/playlist/api-report.md index ddfec2948d..7a732a4a53 100644 --- a/plugins/playlist/api-report.md +++ b/plugins/playlist/api-report.md @@ -8,16 +8,16 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; import { FetchApi } from '@backstage/core-plugin-api'; import { Playlist } from '@backstage/plugin-playlist-common'; import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; import { RouteRef } from '@backstage/core-plugin-api'; // @public (undocumented) -export const EntityPlaylistDialog: ({ - open, - onClose, -}: EntityPlaylistDialogProps) => JSX.Element; +export const EntityPlaylistDialog: ( + props: EntityPlaylistDialogProps, +) => JSX.Element; // @public (undocumented) export type EntityPlaylistDialogProps = { @@ -49,7 +49,7 @@ export interface PlaylistApi { // (undocumented) getPlaylist(playlistId: string): Promise; // (undocumented) - getPlaylistEntities(playlistId: string): Promise; + getPlaylistEntities(playlistId: string): Promise; // (undocumented) removePlaylistEntities( playlistId: string, @@ -80,7 +80,7 @@ export class PlaylistClient implements PlaylistApi { // (undocumented) getPlaylist(playlistId: string): Promise; // (undocumented) - getPlaylistEntities(playlistId: string): Promise; + getPlaylistEntities(playlistId: string): Promise; // (undocumented) removePlaylistEntities( playlistId: string, diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 51cffcca9f..f59fce18db 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -22,14 +22,14 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@backstage/catalog-model": "^1.1.0", - "@backstage/core-components": "^0.11.1-next.2", - "@backstage/core-plugin-api": "^1.0.6-next.2", - "@backstage/errors": "^1.1.0", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/core-components": "^0.11.1-next.3", + "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/plugin-catalog-common": "^1.0.6-next.0", - "@backstage/plugin-catalog-react": "^1.1.4-next.1", - "@backstage/plugin-permission-common": "^0.6.4-next.1", - "@backstage/plugin-permission-react": "^0.4.5-next.1", + "@backstage/plugin-catalog-react": "^1.1.4-next.2", + "@backstage/plugin-permission-common": "^0.6.4-next.2", + "@backstage/plugin-permission-react": "^0.4.5-next.2", "@backstage/plugin-playlist-common": "^0.0.0", "@backstage/plugin-search-react": "^1.1.0-next.2", "@backstage/theme": "^0.2.16", @@ -47,15 +47,14 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "^0.19.0-next.2", - "@backstage/core-app-api": "^1.1.0-next.2", - "@backstage/dev-utils": "^1.0.6-next.1", - "@backstage/test-utils": "^1.2.0-next.2", + "@backstage/cli": "^0.19.0-next.3", + "@backstage/core-app-api": "^1.1.0-next.3", + "@backstage/dev-utils": "^1.0.6-next.2", + "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", - "@types/jest": "*", "@types/node": "*", "cross-fetch": "^3.1.5", "msw": "^0.47.0", diff --git a/plugins/playlist/src/api/PlaylistApi.ts b/plugins/playlist/src/api/PlaylistApi.ts index d0b87ec28a..9a9da1badb 100644 --- a/plugins/playlist/src/api/PlaylistApi.ts +++ b/plugins/playlist/src/api/PlaylistApi.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { Entity } from '@backstage/catalog-model'; import { createApiRef } from '@backstage/core-plugin-api'; import { Playlist, PlaylistMetadata } from '@backstage/plugin-playlist-common'; @@ -62,7 +63,7 @@ export interface PlaylistApi { addPlaylistEntities(playlistId: string, entityRefs: string[]): Promise; - getPlaylistEntities(playlistId: string): Promise; + getPlaylistEntities(playlistId: string): Promise; removePlaylistEntities( playlistId: string, diff --git a/plugins/playlist/src/api/PlaylistClient.test.ts b/plugins/playlist/src/api/PlaylistClient.test.ts index f3b62c19ac..20d4a0bcc8 100644 --- a/plugins/playlist/src/api/PlaylistClient.test.ts +++ b/plugins/playlist/src/api/PlaylistClient.test.ts @@ -215,7 +215,29 @@ describe('PlaylistClient', () => { }); it('getPlaylistEntities', async () => { - const entities = ['component:default/ent1', 'component:default/ent2']; + const entities = [ + { + kind: 'system', + metadata: { + namespace: 'default', + name: 'test-ent', + title: 'Test Ent', + description: 'test ent description', + }, + }, + { + kind: 'component', + metadata: { + namespace: 'foo', + name: 'test-ent2', + title: 'Test Ent 2', + description: 'test ent description 2', + }, + spec: { + type: 'library', + }, + }, + ]; server.use( rest.get(`${mockBaseUrl}/id/entities`, (_, res, ctx) => diff --git a/plugins/playlist/src/api/PlaylistClient.ts b/plugins/playlist/src/api/PlaylistClient.ts index b77aa79733..425b185de8 100644 --- a/plugins/playlist/src/api/PlaylistClient.ts +++ b/plugins/playlist/src/api/PlaylistClient.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { Entity } from '@backstage/catalog-model'; import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'; import { ResponseError } from '@backstage/errors'; import { Playlist, PlaylistMetadata } from '@backstage/plugin-playlist-common'; @@ -142,7 +143,7 @@ export class PlaylistClient implements PlaylistApi { } } - async getPlaylistEntities(playlistId: string): Promise { + async getPlaylistEntities(playlistId: string): Promise { const baseUrl = await this.discoveryApi.getBaseUrl('playlist'); const resp = await this.fetchApi.fetch( `${baseUrl}/${playlistId}/entities`, diff --git a/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.tsx b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.tsx index 474a9abb1f..247f737f3f 100644 --- a/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.tsx +++ b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.tsx @@ -78,10 +78,9 @@ export type EntityPlaylistDialogProps = { onClose: () => void; }; -export const EntityPlaylistDialog = ({ - open, - onClose, -}: EntityPlaylistDialogProps) => { +export const EntityPlaylistDialog = (props: EntityPlaylistDialogProps) => { + const { open, onClose } = props; + const classes = useStyles(); const navigate = useNavigate(); const { entity } = useAsyncEntity(); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx index 3dfd89fda9..f7720b25c1 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx @@ -15,11 +15,7 @@ */ import { ErrorApi, errorApiRef } from '@backstage/core-plugin-api'; -import { - CatalogApi, - catalogApiRef, - entityRouteRef, -} from '@backstage/plugin-catalog-react'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { PermissionApi, @@ -47,17 +43,6 @@ jest.mock('./AddEntitiesDrawer', () => ({ describe('PlaylistEntitiesTable', () => { const errorApi: Partial = { post: jest.fn() }; - const playlistApi: Partial = { - getPlaylistEntities: jest - .fn() - .mockImplementation(async () => [ - 'system:default/test-ent', - 'component:foo/test-ent2', - ]), - addPlaylistEntities: jest.fn().mockImplementation(async () => {}), - removePlaylistEntities: jest.fn().mockImplementation(async () => {}), - }; - const sampleEntities = [ { kind: 'system', @@ -81,10 +66,12 @@ describe('PlaylistEntitiesTable', () => { }, }, ]; - const catalogApi: Partial = { - getEntities: jest + const playlistApi: Partial = { + getPlaylistEntities: jest .fn() - .mockImplementation(async () => ({ items: sampleEntities })), + .mockImplementation(async () => sampleEntities), + addPlaylistEntities: jest.fn().mockImplementation(async () => {}), + removePlaylistEntities: jest.fn().mockImplementation(async () => {}), }; const mockAuthorize = jest @@ -97,7 +84,6 @@ describe('PlaylistEntitiesTable', () => { new Map() }}> { const rendered = await render(); expect(playlistApi.getPlaylistEntities).toHaveBeenCalledWith('playlist-id'); - expect(catalogApi.getEntities).toHaveBeenCalledWith({ - filter: [ - { - kind: 'system', - 'metadata.namespace': 'default', - 'metadata.name': 'test-ent', - }, - { - kind: 'component', - 'metadata.namespace': 'foo', - 'metadata.name': 'test-ent2', - }, - ], - fields: [ - 'kind', - 'metadata.namespace', - 'metadata.name', - 'metadata.title', - 'metadata.description', - 'spec.type', - ], - }); expect(rendered.getByText('Test Ent')).toBeInTheDocument(); expect(rendered.getByText('system')).toBeInTheDocument(); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx index 0fa78b19bd..f499f59a61 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx @@ -14,11 +14,7 @@ * limitations under the License. */ -import { - Entity, - parseEntityRef, - stringifyEntityRef, -} from '@backstage/catalog-model'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { ErrorPanel, SubvalueCell, @@ -26,7 +22,7 @@ import { TableFilter, } from '@backstage/core-components'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; -import { catalogApiRef, EntityRefLink } from '@backstage/plugin-catalog-react'; +import { EntityRefLink } from '@backstage/plugin-catalog-react'; import { usePermission } from '@backstage/plugin-permission-react'; import { permissions } from '@backstage/plugin-playlist-common'; import AddBoxIcon from '@material-ui/icons/AddBox'; @@ -43,7 +39,6 @@ export const PlaylistEntitiesTable = ({ }: { playlistId: string; }) => { - const catalogApi = useApi(catalogApiRef); const errorApi = useApi(errorApiRef); const playlistApi = useApi(playlistApiRef); const [openAddEntitiesDrawer, setOpenAddEntitiesDrawer] = useState(false); @@ -53,39 +48,10 @@ export const PlaylistEntitiesTable = ({ resourceRef: playlistId, }); - const [{ value: entities, loading, error }, loadEntities] = - useAsyncFn(async () => { - const entityRefs = await playlistApi.getPlaylistEntities(playlistId); - if (!entityRefs.length) { - return []; - } - - const filter = entityRefs.map(ref => { - const compoundRef = parseEntityRef(ref); - return { - kind: compoundRef.kind, - 'metadata.namespace': compoundRef.namespace, - 'metadata.name': compoundRef.name, - }; - }); - - // TODO(kuanpg): entities in this playlist that no longer exist in the catalog will be - // excluded from this response, we need a way to clean up these orphaned refs potentially - // via catalog events (https://github.com/backstage/backstage/issues/8219) - return ( - await catalogApi.getEntities({ - filter, - fields: [ - 'kind', - 'metadata.namespace', - 'metadata.name', - 'metadata.title', - 'metadata.description', - 'spec.type', - ], - }) - ).items; - }, [catalogApi, playlistApi]); + const [{ value: entities, loading, error }, loadEntities] = useAsyncFn( + () => playlistApi.getPlaylistEntities(playlistId), + [playlistApi], + ); useEffect(() => { loadEntities(); @@ -190,7 +156,7 @@ export const PlaylistEntitiesTable = ({ data={entities ?? []} filters={filters} icons={{ - ...Table.tableIcons, + ...Table.icons, Search: forwardRef((props, ref) => ( )), diff --git a/yarn.lock b/yarn.lock index d55434a22a..02659263e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3010,7 +3010,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@^1.1.0-next.2, @backstage/catalog-client@workspace:packages/catalog-client": +"@backstage/catalog-client@1.1.0-next.2, @backstage/catalog-client@^1.1.0-next.2, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" dependencies: @@ -6222,6 +6222,85 @@ __metadata: languageName: node linkType: hard +"@backstage/plugin-playlist-backend@^0.0.0, @backstage/plugin-playlist-backend@workspace:plugins/playlist-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-playlist-backend@workspace:plugins/playlist-backend" + dependencies: + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-client": 1.1.0-next.2 + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/config": ^1.0.2-next.0 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-node": ^0.6.5-next.3 + "@backstage/plugin-playlist-common": ^0.0.0 + "@types/express": "*" + "@types/supertest": ^2.0.8 + express: ^4.17.1 + express-promise-router: ^4.1.0 + knex: ^2.0.0 + msw: ^0.47.0 + node-fetch: ^2.6.7 + supertest: ^6.1.3 + uuid: ^8.2.0 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-playlist-common@^0.0.0, @backstage/plugin-playlist-common@workspace:plugins/playlist-common": + version: 0.0.0-use.local + resolution: "@backstage/plugin-playlist-common@workspace:plugins/playlist-common" + dependencies: + "@backstage/cli": ^0.19.0-next.3 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + languageName: unknown + linkType: soft + +"@backstage/plugin-playlist@^0.0.0, @backstage/plugin-playlist@workspace:plugins/playlist": + version: 0.0.0-use.local + resolution: "@backstage/plugin-playlist@workspace:plugins/playlist" + dependencies: + "@backstage/catalog-model": ^1.1.1-next.0 + "@backstage/cli": ^0.19.0-next.3 + "@backstage/core-app-api": ^1.1.0-next.3 + "@backstage/core-components": ^0.11.1-next.3 + "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-catalog-common": ^1.0.6-next.0 + "@backstage/plugin-catalog-react": ^1.1.4-next.2 + "@backstage/plugin-permission-common": ^0.6.4-next.2 + "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/plugin-playlist-common": ^0.0.0 + "@backstage/plugin-search-react": ^1.1.0-next.2 + "@backstage/test-utils": ^1.2.0-next.3 + "@backstage/theme": ^0.2.16 + "@material-ui/core": ^4.9.13 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": ^4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/react-hooks": ^8.0.0 + "@testing-library/user-event": ^14.0.0 + "@types/node": "*" + cross-fetch: ^3.1.5 + lodash: ^4.17.21 + msw: ^0.47.0 + qs: ^6.9.4 + react-hook-form: ^7.13.0 + react-use: ^17.2.4 + swr: ^1.1.2 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-router: 6.0.0-beta.0 || ^6.3.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + "@backstage/plugin-proxy-backend@^0.2.30-next.2, @backstage/plugin-proxy-backend@workspace:plugins/proxy-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-proxy-backend@workspace:plugins/proxy-backend" @@ -22470,6 +22549,7 @@ __metadata: "@backstage/plugin-org": ^0.5.9-next.3 "@backstage/plugin-pagerduty": 0.5.2-next.3 "@backstage/plugin-permission-react": ^0.4.5-next.2 + "@backstage/plugin-playlist": ^0.0.0 "@backstage/plugin-rollbar": ^0.4.9-next.3 "@backstage/plugin-scaffolder": ^1.6.0-next.3 "@backstage/plugin-search": ^1.0.2-next.3 @@ -22557,6 +22637,7 @@ __metadata: "@backstage/plugin-permission-backend": ^0.5.11-next.2 "@backstage/plugin-permission-common": ^0.6.4-next.2 "@backstage/plugin-permission-node": ^0.6.5-next.3 + "@backstage/plugin-playlist-backend": ^0.0.0 "@backstage/plugin-proxy-backend": ^0.2.30-next.2 "@backstage/plugin-rollbar-backend": ^0.1.33-next.3 "@backstage/plugin-scaffolder-backend": ^1.6.0-next.3 From 02a5296f859aa605a53b32d4b4c5a922740867a7 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Fri, 16 Sep 2022 14:34:33 -0400 Subject: [PATCH 34/95] refactor(search-react): address review comment Signed-off-by: Phil Kuang --- plugins/search-react/package.json | 1 + .../SearchFilter.Autocomplete.tsx | 3 +- .../SearchFilter/SearchFilter.test.tsx | 16 ++---- .../components/SearchFilter/SearchFilter.tsx | 6 +-- .../src/context/SearchContext.test.tsx | 54 +++++++++++++++++++ .../src/context/SearchContext.tsx | 10 ++++ yarn.lock | 1 + 7 files changed, 73 insertions(+), 18 deletions(-) diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 826d751353..8de637d46c 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -40,6 +40,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "lodash": "^4.17.21", "qs": "^6.9.4", "react-use": "^17.3.2" }, diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx index c14dfdfa7e..35d1f376e5 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.tsx @@ -62,7 +62,7 @@ export const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => { defaultValues, valuesDebounceMs, ); - const { filters, setFilters, setPageCursor } = useSearch(); + const { filters, setFilters } = useSearch(); const filterValue = (filters[name] as string | string[] | undefined) || (multiple ? [] : null); @@ -79,7 +79,6 @@ export const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => { } return { ...others }; }); - setPageCursor(undefined); }; // Provide the input field. diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx index 27fbae237c..89a1818e8d 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx @@ -33,7 +33,6 @@ describe('SearchFilter', () => { term: '', filters: {}, types: [], - pageCursor: 'abc123', }; const label = 'Field'; @@ -139,10 +138,7 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ - filters: { field: [values[0]] }, - pageCursor: undefined, - }), + expect.objectContaining({ filters: { field: [values[0]] } }), ); }); @@ -150,7 +146,7 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters: {}, pageCursor: undefined }), + expect.objectContaining({ filters: {} }), ); }); }); @@ -174,7 +170,6 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { ...filters, field: [values[0]] }, - pageCursor: undefined, }), ); }); @@ -183,7 +178,7 @@ describe('SearchFilter', () => { await userEvent.click(checkBox); await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters, pageCursor: undefined }), + expect.objectContaining({ filters }), ); }); }); @@ -342,7 +337,6 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { [name]: values[0] }, - pageCursor: undefined, }), ); }); @@ -359,7 +353,6 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: {}, - pageCursor: undefined, }), ); }); @@ -395,7 +388,6 @@ describe('SearchFilter', () => { expect(query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { ...filters, [name]: values[0] }, - pageCursor: undefined, }), ); }); @@ -410,7 +402,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(query).toHaveBeenLastCalledWith( - expect.objectContaining({ filters, pageCursor: undefined }), + expect.objectContaining({ filters }), ); }); }); diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx index 958caf0927..2a6d7baafa 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.tsx @@ -82,7 +82,7 @@ export const CheckboxFilter = (props: SearchFilterComponentProps) => { valuesDebounceMs, } = props; const classes = useStyles(); - const { filters, setFilters, setPageCursor } = useSearch(); + const { filters, setFilters } = useSearch(); useDefaultFilterValue(name, defaultValue); const asyncValues = typeof givenValues === 'function' ? givenValues : undefined; @@ -106,7 +106,6 @@ export const CheckboxFilter = (props: SearchFilterComponentProps) => { const items = checked ? [...rest, value] : rest; return items.length ? { ...others, [name]: items } : others; }); - setPageCursor(undefined); }; return ( @@ -162,7 +161,7 @@ export const SelectFilter = (props: SearchFilterComponentProps) => { defaultValues, valuesDebounceMs, ); - const { filters, setFilters, setPageCursor } = useSearch(); + const { filters, setFilters } = useSearch(); const handleChange = (e: ChangeEvent<{ value: unknown }>) => { const { @@ -173,7 +172,6 @@ export const SelectFilter = (props: SearchFilterComponentProps) => { const { [name]: filter, ...others } = prevFilters; return value ? { ...others, [name]: value as string } : others; }); - setPageCursor(undefined); }; return ( diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index 68c79d3a5e..b5888fa8a9 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -160,6 +160,60 @@ describe('SearchContext', () => { expect(result.current.pageCursor).toBeUndefined(); }); + + it('When filters are cleared', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState: { + ...initialState, + filters: { foo: 'bar' }, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }, + }); + + await waitForNextUpdate(); + + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + + act(() => { + result.current.setFilters({}); + }); + + await waitForNextUpdate(); + + expect(result.current.pageCursor).toBeUndefined(); + }); + + it('When filters are set (and different from previous)', async () => { + const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + wrapper, + initialProps: { + initialState: { + ...initialState, + filters: { foo: 'bar' }, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }, + }); + + await waitForNextUpdate(); + + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + + act(() => { + result.current.setFilters({ foo: 'test' }); + }); + + await waitForNextUpdate(); + + expect(result.current.pageCursor).toBeUndefined(); + }); }); describe('Performs search (and sets results)', () => { diff --git a/plugins/search-react/src/context/SearchContext.tsx b/plugins/search-react/src/context/SearchContext.tsx index 7faa743c9d..6557f04c15 100644 --- a/plugins/search-react/src/context/SearchContext.tsx +++ b/plugins/search-react/src/context/SearchContext.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import { isEqual } from 'lodash'; import React, { PropsWithChildren, useCallback, @@ -115,6 +116,7 @@ const useSearchContextValue = ( ); const prevTerm = usePrevious(term); + const prevFilters = usePrevious(filters); const result = useAsync( () => @@ -146,6 +148,14 @@ const useSearchContextValue = ( } }, [term, prevTerm, setPageCursor]); + useEffect(() => { + // Any time filters is reset, we want to start from page 0. + // Only reset the page if it has been modified by the user at least once, the initial state must not reset the page. + if (prevFilters !== undefined && !isEqual(filters, prevFilters)) { + setPageCursor(undefined); + } + }, [filters, prevFilters, setPageCursor]); + const value: SearchContextValue = { result, filters, diff --git a/yarn.lock b/yarn.lock index 02659263e8..659cc76d23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6712,6 +6712,7 @@ __metadata: "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 + lodash: ^4.17.21 qs: ^6.9.4 react-use: ^17.3.2 peerDependencies: From cc63eb8611d86d12b7a28a08b4ec33a658e4277e Mon Sep 17 00:00:00 2001 From: Tomasz Szuba Date: Tue, 13 Sep 2022 13:43:40 +0200 Subject: [PATCH 35/95] Sort entries in skeleton.tar.gz Signed-off-by: Tomasz Szuba --- .changeset/clever-rocks-train.md | 5 +++++ .../cli/src/lib/packager/createDistWorkspace.ts | 14 ++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 .changeset/clever-rocks-train.md diff --git a/.changeset/clever-rocks-train.md b/.changeset/clever-rocks-train.md new file mode 100644 index 0000000000..91d3964cdd --- /dev/null +++ b/.changeset/clever-rocks-train.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Sort entries in skeleton.tar.gz for better docker layer caching diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 53e00ab6d9..5451a873f7 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -22,7 +22,7 @@ import { relative as relativePath, } from 'path'; import { tmpdir } from 'os'; -import tar, { CreateOptions } from 'tar'; +import tar, { CreateOptions, FileOptions } from 'tar'; import partition from 'lodash/partition'; import { paths } from '../paths'; import { run } from '../run'; @@ -214,10 +214,12 @@ export async function createDistWorkspace( } if (options.skeleton) { - const skeletonFiles = targets.map(target => { - const dir = relativePath(paths.targetRoot, target.dir); - return joinPath(dir, 'package.json'); - }); + const skeletonFiles = targets + .map(target => { + const dir = relativePath(paths.targetRoot, target.dir); + return joinPath(dir, 'package.json'); + }) + .sort(); await tar.create( { @@ -226,7 +228,7 @@ export async function createDistWorkspace( portable: true, noMtime: true, gzip: options.skeleton.endsWith('.gz'), - } as CreateOptions & { noMtime: boolean }, + } as CreateOptions & FileOptions & { noMtime: boolean }, skeletonFiles, ); } From e6541555d8d714f951b1b252f18b9d8e75856e3b Mon Sep 17 00:00:00 2001 From: Callen Barton <7515844+cal5barton@users.noreply.github.com> Date: Fri, 16 Sep 2022 16:51:30 -0600 Subject: [PATCH 36/95] Update ADOPTERS.md Signed-off-by: Callen Barton <7515844+cal5barton@users.noreply.github.com> --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 48c69d21bd..4378eb14f9 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -202,7 +202,7 @@ _You can do this by using the [Adopter form](https://form.typeform.com/to/zcOaKi | [Skillz](https://skillz.com/) | [Peiman Jafari](https://github.com/peimanja) | Internal developers portal for technical documentations, components ownership and relationship, software templates and integrations with internal tools | | [Telus](https://www.telus.com/en/) | [Leo Li](mailto:leo.li@telus.com), [Laurent Robichaud](mailto:laurent.robichaud@telus.com), [Seb Barre](https://github.com/sbarre) | Simplifying the developer experience through centralized team member portals. Our current focus includes the adoption of Tech Docs, Software Catalog, Software Templates, the plethora of plugins, and contributing features back to Backstage. 🤖 | | [Fidelity Investments](https://fidelity.com) | [Ankita Upadhyay](mailto:ankita.upadhyay@fmr.com) | Getting started with the adoption for Monorepo projects | -| [Verisk](https://verisk.com) | [Callen Barton](mailto:cbarton@verisk.com) | Developer portal to quickly create and deploy microservices. | +| [Verisk](https://verisk.com) | [Callen Barton](mailto:#xw_architecture@verisk.com), [Kevin Johnson](mailto:#xw_architecture@verisk.com) | Developer portal to quickly create and deploy microservices. | | [iodigital](https://iodigital.com) | [Jan-Willem Mulder](mailto:jan-willem.mulder@iodigital.com) | Internal developer portal for discovery of applications, projects and teams. Using several plugins like the Software Catalog and Tech Insights for promoting best practices and supporting our SDLC toolchain | | [Fanatics](https://www.fanaticsinc.com/) | [Rory Scott](mailto:rscott@fanatics.com) | Internal Portal consolidating documentation, making it easier to manage applications, internal developer community platform, and self-service cloud infrastructure + pipelines. | | [Appfolio](https://appfolio.com) | [Andy Vaughn](mailto:andy.vaughn@appfolio.com) | Internal software catalog, tech radar, documentation portal to disambiguate software and domain ownership, foster exploration of available developer platform services and tools, improve communication, democratize documentation and knowledge sharing, and coordinate the software lifecycle; all in service of a best-in-class developer experience. | From fc4d6382965afe7f1f9524260950081cd43bf1a8 Mon Sep 17 00:00:00 2001 From: Leena <19555355+sploschee@users.noreply.github.com> Date: Sat, 17 Sep 2022 19:20:26 +0100 Subject: [PATCH 37/95] @backstage/docs: fix dead link Active LTS Releases was `https://nodejs.org/en/about/releases/` now `https://nodejs.org/en/blog/release/` Signed-off-by: Leena <19555355+sploschee@users.noreply.github.com> --- docs/getting-started/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index d560b97eae..ade73d3f68 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -25,7 +25,7 @@ guide to do a repository-based installation. [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) - An account with elevated rights to install the dependencies - `curl` or `wget` installed -- Node.js [Active LTS Release](https://nodejs.org/en/about/releases/) installed using one of these +- Node.js [Active LTS Release](https://nodejs.org/en/blog/release/) installed using one of these methods: - Using `nvm` (recommended) - [Installing nvm](https://github.com/nvm-sh/nvm#install--update-script) From 3505e07b6c3adac83dcc9869582a271bf0b91c66 Mon Sep 17 00:00:00 2001 From: Leena <19555355+sploschee@users.noreply.github.com> Date: Sat, 17 Sep 2022 21:01:48 +0100 Subject: [PATCH 38/95] fix(docs): minor typo `provider` was missing an `r` Signed-off-by: Leena <19555355+sploschee@users.noreply.github.com> --- docs/auth/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/auth/index.md b/docs/auth/index.md index 8d303c776d..ab04d3ed87 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -65,7 +65,7 @@ the local `auth.environment` setting will be selected. > and access to a Backstage Identity Token, which can be passed to backend > plugins. -Using an authentication provide for sign-in is something you need to configure +Using an authentication provider for sign-in is something you need to configure both in the frontend app, as well as the `auth` backend plugin. For information on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md). The rest of this section will focus on how to configure sign-in for the frontend app. From ae202dc3bc15478c9372503e1d43d26d556a9a0d Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Mon, 19 Sep 2022 08:29:23 +0200 Subject: [PATCH 39/95] Update .changeset/smooth-camels-melt.md Co-authored-by: Ben Lambert Signed-off-by: Magnus Persson --- .changeset/smooth-camels-melt.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/smooth-camels-melt.md b/.changeset/smooth-camels-melt.md index bd816827a4..7d76bbd9ba 100644 --- a/.changeset/smooth-camels-melt.md +++ b/.changeset/smooth-camels-melt.md @@ -2,4 +2,4 @@ '@backstage/backend-common': patch --- -The `branch` command has been added to the `Git` isomorphic-git wrapper. +The `branch` command has been added to the `isomorphic-git` wrapper. From 50577161a4e3d82fdd6bc96f4e1b5ec082d64c9d Mon Sep 17 00:00:00 2001 From: Tim Jacomb Date: Mon, 19 Sep 2022 08:48:35 +0100 Subject: [PATCH 40/95] Prettier Signed-off-by: Tim Jacomb --- plugins/jenkins-backend/src/service/router.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/jenkins-backend/src/service/router.ts b/plugins/jenkins-backend/src/service/router.ts index 395efffb9c..df4c3b5a11 100644 --- a/plugins/jenkins-backend/src/service/router.ts +++ b/plugins/jenkins-backend/src/service/router.ts @@ -27,7 +27,7 @@ import { } from '@backstage/plugin-permission-common'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; import { stringifyEntityRef } from '@backstage/catalog-model'; -import { stringifyError } from "@backstage/errors"; +import { stringifyError } from '@backstage/errors'; /** @public */ export interface RouterOptions { @@ -92,7 +92,6 @@ export async function createRouter( backstageToken: token, }); - try { const projects = await jenkinsApi.getProjects(jenkinsInfo, branches); @@ -103,9 +102,13 @@ export async function createRouter( // Promise.any, used in the getProjects call returns an Aggregate error message with a useless error message 'AggregateError: All promises were rejected' // extract useful information ourselves if (err.errors) { - throw new Error(`Unable to fetch projects, for ${jenkinsInfo.jobFullName}: ${stringifyError(err.errors)}`) + throw new Error( + `Unable to fetch projects, for ${ + jenkinsInfo.jobFullName + }: ${stringifyError(err.errors)}`, + ); } - throw err + throw err; } }, ); From 108cdc39124bdb8e011bc614cd513cff695e88a0 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Fri, 26 Aug 2022 10:46:16 +0200 Subject: [PATCH 41/95] feat: add new user settings backend Adding a new user settings backend and PersistentStorage to store user related settings in the database. Signed-off-by: Dominik Schwank --- .changeset/healthy-oranges-fly.md | 8 + .github/CODEOWNERS | 1 + packages/core-app-api/api-report.md | 29 ++ packages/core-app-api/package.json | 2 + .../StorageApi/PersistentStorage.test.ts | 324 +++++++++++++++ .../StorageApi/PersistentStorage.ts | 193 +++++++++ .../apis/implementations/StorageApi/index.ts | 1 + plugins/user-settings-backend/.eslintrc.js | 1 + plugins/user-settings-backend/README.md | 104 +++++ plugins/user-settings-backend/api-report.md | 177 +++++++++ .../migrations/20220824183000_init.js | 41 ++ plugins/user-settings-backend/package.json | 52 +++ .../DatabaseUserSettingsStore.test.ts | 373 ++++++++++++++++++ .../src/database/DatabaseUserSettingsStore.ts | 143 +++++++ .../src/database/UserSettingsStore.ts | 65 +++ .../src/database/index.ts | 20 + plugins/user-settings-backend/src/index.ts | 17 + plugins/user-settings-backend/src/run.ts | 33 ++ .../src/service/index.ts | 20 + .../src/service/router.test.ts | 319 +++++++++++++++ .../src/service/router.ts | 168 ++++++++ .../src/service/standaloneServer.ts | 82 ++++ .../user-settings-backend/src/setupTests.ts | 16 + yarn.lock | 29 +- 24 files changed, 2215 insertions(+), 3 deletions(-) create mode 100644 .changeset/healthy-oranges-fly.md create mode 100644 packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts create mode 100644 packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts create mode 100644 plugins/user-settings-backend/.eslintrc.js create mode 100644 plugins/user-settings-backend/README.md create mode 100644 plugins/user-settings-backend/api-report.md create mode 100644 plugins/user-settings-backend/migrations/20220824183000_init.js create mode 100644 plugins/user-settings-backend/package.json create mode 100644 plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts create mode 100644 plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts create mode 100644 plugins/user-settings-backend/src/database/UserSettingsStore.ts create mode 100644 plugins/user-settings-backend/src/database/index.ts create mode 100644 plugins/user-settings-backend/src/index.ts create mode 100644 plugins/user-settings-backend/src/run.ts create mode 100644 plugins/user-settings-backend/src/service/index.ts create mode 100644 plugins/user-settings-backend/src/service/router.test.ts create mode 100644 plugins/user-settings-backend/src/service/router.ts create mode 100644 plugins/user-settings-backend/src/service/standaloneServer.ts create mode 100644 plugins/user-settings-backend/src/setupTests.ts diff --git a/.changeset/healthy-oranges-fly.md b/.changeset/healthy-oranges-fly.md new file mode 100644 index 0000000000..da6530b903 --- /dev/null +++ b/.changeset/healthy-oranges-fly.md @@ -0,0 +1,8 @@ +--- +'@backstage/core-app-api': minor +'@backstage/plugin-user-settings-backend': minor +--- + +Add new plugin @backstage/user-settings-backend to store user related settings +in the database. Additionally adding a PersistentStorage implementation to use +easily use the new plugin as drop-in replacement for the WebStorage. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f00771d29d..599a83cedf 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -56,6 +56,7 @@ yarn.lock @backstage/reviewers @backst /plugins/stack-overflow-backend @backstage/reviewers @backstage/techdocs-core /plugins/techdocs @backstage/reviewers @backstage/techdocs-core /plugins/techdocs-* @backstage/reviewers @backstage/techdocs-core +/plugins/user-settings-backend @backstage/reviewers @backstage/sda-se-reviewers /tech-insights-backend @backstage/reviewers @xantier @iain-b /tech-insights-backend-module-jsonfc @backstage/reviewers @xantier @iain-b /tech-insights-tech-insights-common @backstage/reviewers @xantier @iain-b diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index f2bc4b6665..de3afdcbd4 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -506,6 +506,35 @@ export type OneLoginAuthCreateOptions = { provider?: AuthProviderInfo; }; +// @public +export class PersistentStorage implements StorageApi { + constructor( + namespace: string, + fetchApi: FetchApi, + discoveryApi: DiscoveryApi, + errorApi: ErrorApi, + ); + // (undocumented) + static create(options: { + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + errorApi: ErrorApi; + namespace?: string; + }): PersistentStorage; + // (undocumented) + forBucket(name: string): StorageApi; + // (undocumented) + observe$( + key: string, + ): Observable>; + // (undocumented) + remove(key: string): Promise; + // (undocumented) + set(key: string, data: T): Promise; + // (undocumented) + snapshot(key: string): StorageValueSnapshot; +} + // @public export class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 8532997477..632c429361 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -34,6 +34,8 @@ "dependencies": { "@backstage/config": "^1.0.2-next.0", "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.0", + "@backstage/plugin-permission-common": "^0.6.4-next.0", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts new file mode 100644 index 0000000000..6cea8dde5b --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts @@ -0,0 +1,324 @@ +/* + * 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 { PersistentStorage } from './PersistentStorage'; +import { ErrorApi, FetchApi, StorageApi } from '@backstage/core-plugin-api'; +import { DiscoveryApi } from '@backstage/plugin-permission-common'; +import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; + +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; + +const server = setupServer(); + +describe('Persistent Storage API', () => { + setupRequestMockHandlers(server); + const mockBaseUrl = 'http://backstage:9191/api'; + const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; + const mockDiscoveryApi = { getBaseUrl: async () => mockBaseUrl }; + + const createPersistentStorage = ( + args?: Partial<{ + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + errorApi: ErrorApi; + namespace?: string; + }>, + ): StorageApi => { + return PersistentStorage.create({ + errorApi: mockErrorApi, + fetchApi: new MockFetchApi(), + discoveryApi: mockDiscoveryApi, + ...args, + }); + }; + + beforeEach(() => { + server.use( + rest.get(`${mockBaseUrl}/`, async (_req, res, ctx) => { + return res(ctx.json([])); + }), + ); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should return undefined for values which are unset', async () => { + const storage = createPersistentStorage(); + + server.use( + rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { + return res(ctx.json({ value: 'a' })); + }), + ); + + expect(storage.snapshot('myfakekey').value).toBeUndefined(); + expect(storage.snapshot('myfakekey')).toEqual({ + key: 'myfakekey', + presence: 'unknown', + value: undefined, + }); + }); + + it('should allow setting of a simple data structure', async () => { + const storage = createPersistentStorage(); + const dummyValue = 'a'; + + server.use( + rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(dummyValue) }; + expect(body).toEqual(data); + + return res(ctx.json(data)); + }), + ); + + await storage.set('my-key', dummyValue); + }); + + it('should allow setting of a complex data structure', async () => { + const storage = createPersistentStorage(); + const dummyValue = { + some: 'nice data', + with: { nested: 'values', nice: true }, + }; + + server.use( + rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(dummyValue) }; + expect(body).toEqual(data); + + return res(ctx.json(data)); + }), + ); + + await storage.set('my-key', dummyValue); + }); + + it('should subscribe to key changes when setting a new value', async () => { + const storage = createPersistentStorage(); + + const wrongKeyNextHandler = jest.fn(); + const selectedKeyNextHandler = jest.fn(); + const mockData = { hello: 'im a great new value' }; + + server.use( + rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(mockData) }; + expect(body).toEqual(data); + + return res(ctx.json(data)); + }), + ); + + await new Promise(resolve => { + storage.observe$('correctKey').subscribe({ + next: snapshot => { + selectedKeyNextHandler(snapshot); + if (snapshot.presence === 'present') { + resolve(); + } + }, + }); + + storage.observe$('wrongKey').subscribe({ next: wrongKeyNextHandler }); + + storage.set('correctKey', mockData); + }); + + expect(wrongKeyNextHandler).toHaveBeenCalledTimes(0); + expect(selectedKeyNextHandler).toHaveBeenCalledTimes(1); + expect(selectedKeyNextHandler).toHaveBeenCalledWith({ + key: 'correctKey', + presence: 'present', + value: mockData, + }); + }); + + it('should subscribe to key changes when deleting a value', async () => { + const storage = createPersistentStorage(); + + const wrongKeyNextHandler = jest.fn(); + const selectedKeyNextHandler = jest.fn(); + + server.use( + rest.delete(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { + return res(ctx.status(204)); + }), + ); + + await new Promise(resolve => { + storage.observe$('correctKey').subscribe({ + next: snapshot => { + selectedKeyNextHandler(snapshot); + if (snapshot.presence === 'absent') { + resolve(); + } + }, + }); + + storage.observe$('wrongKey').subscribe({ next: wrongKeyNextHandler }); + + storage.remove('correctKey'); + }); + + expect(wrongKeyNextHandler).toHaveBeenCalledTimes(0); + expect(selectedKeyNextHandler).toHaveBeenCalledTimes(1); + expect(selectedKeyNextHandler).toHaveBeenCalledWith({ + key: 'correctKey', + presence: 'absent', + value: undefined, + }); + }); + + it('should not clash with other namespaces when creating buckets', async () => { + const rootStorage = createPersistentStorage(); + const selectedKeyNextHandler = jest.fn(); + + server.use( + rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const { bucket, key } = req.params; + const { value } = await req.json(); + + expect(bucket).toEqual('default.profile.something.deep'); + expect(key).toEqual('test2'); + + return res(ctx.json({ value })); + }), + rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const { bucket, key } = req.params; + + expect(bucket).toEqual('default.profile/something'); + expect(key).toEqual('deep/test2'); + + return res(ctx.status(404)); + }), + ); + + // when getting key test2 it will translate to default.profile.something.deep/test2 + const firstStorage = rootStorage + .forBucket('profile') + .forBucket('something') + .forBucket('deep'); + // when getting key deep/test2 it will translate to default.profile.something/deep/test2 + const secondStorage = rootStorage.forBucket('profile/something'); + + await firstStorage.set('test2', { error: true }); + + await new Promise(resolve => { + secondStorage.observe$('deep/test2').subscribe({ + next: snapshot => { + selectedKeyNextHandler(snapshot); + if (snapshot.presence === 'absent') { + resolve(); + } + }, + }); + + secondStorage.snapshot('deep/test2'); + }); + + expect(selectedKeyNextHandler).toHaveBeenCalledWith({ + key: 'deep/test2', + presence: 'absent', + value: undefined, + }); + expect(mockErrorApi.post).not.toHaveBeenCalled(); + }); + + it('should call the error api when the json can not be parsed in local storage', async () => { + const selectedKeyNextHandler = jest.fn(); + const rootStorage = createPersistentStorage({ + namespace: 'Test.Mock.Thing', + }); + + server.use( + rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + const { bucket, key } = req.params; + + expect(bucket).toEqual('Test.Mock.Thing'); + expect(key).toEqual('key'); + + return res(ctx.text('{ invalid: json string }')); + }), + ); + + await new Promise(resolve => { + rootStorage.observe$('key').subscribe({ + next: snapshot => { + selectedKeyNextHandler(snapshot); + if (snapshot.presence === 'absent') { + resolve(); + } + }, + }); + + rootStorage.snapshot('key'); + }); + + expect(selectedKeyNextHandler).toHaveBeenCalledWith({ + key: 'key', + presence: 'absent', + value: undefined, + }); + expect(mockErrorApi.post).toHaveBeenCalledWith(expect.any(Error)); + }); + + it('should freeze the snapshot value', async () => { + const storage = createPersistentStorage(); + const selectedKeyNextHandler = jest.fn(); + const data = { foo: 'bar', baz: [{ foo: 'bar' }] }; + + server.use( + rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { + return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) }))); + }), + ); + + await new Promise(resolve => { + storage.observe$('key').subscribe({ + next: snapshot => { + selectedKeyNextHandler(snapshot); + if (snapshot.presence === 'present') { + resolve(); + } + }, + }); + + storage.snapshot('key'); + }); + + expect(selectedKeyNextHandler).toHaveBeenCalledWith({ + key: 'key', + presence: 'present', + value: { baz: [{ foo: 'bar' }], foo: 'bar' }, + }); + + const snapshot = selectedKeyNextHandler.mock.calls[0][0]; + expect(() => { + snapshot.value.foo = 'buzz'; + }).toThrow(/Cannot assign to read only property/); + expect(() => { + snapshot.value.baz[0].foo = 'buzz'; + }).toThrow(/Cannot assign to read only property/); + expect(() => { + snapshot.value.baz.push({ foo: 'buzz' }); + }).toThrow(/Cannot add property 1, object is not extensible/); + }); +}); diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts new file mode 100644 index 0000000000..4ebf635cd9 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts @@ -0,0 +1,193 @@ +/* + * 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 { + DiscoveryApi, + ErrorApi, + FetchApi, + StorageApi, + StorageValueSnapshot, +} from '@backstage/core-plugin-api'; +import { NotFoundError } from '@backstage/errors'; +import { JsonValue, Observable } from '@backstage/types'; +import ObservableImpl from 'zen-observable'; + +const buckets = new Map(); + +/** + * An implementation of the storage API, that uses the user-settings backend to + * persist the data in the DB. + * + * @public + */ +export class PersistentStorage implements StorageApi { + private subscribers = new Set< + ZenObservable.SubscriptionObserver> + >(); + + private readonly observable = new ObservableImpl< + StorageValueSnapshot + >(subscriber => { + this.subscribers.add(subscriber); + return () => { + this.subscribers.delete(subscriber); + }; + }); + + constructor( + private readonly namespace: string, + private readonly fetchApi: FetchApi, + private readonly discoveryApi: DiscoveryApi, + private readonly errorApi: ErrorApi, + ) {} + + static create(options: { + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + errorApi: ErrorApi; + namespace?: string; + }): PersistentStorage { + return new PersistentStorage( + options.namespace ?? 'default', + options.fetchApi, + options.discoveryApi, + options.errorApi, + ); + } + + forBucket(name: string): StorageApi { + // use dot instead of slash separator to have nicer URLs + const bucketPath = `${this.namespace}.${name}`; + + if (!buckets.has(bucketPath)) { + buckets.set( + bucketPath, + new PersistentStorage( + bucketPath, + this.fetchApi, + this.discoveryApi, + this.errorApi, + ), + ); + } + + return buckets.get(bucketPath)!; + } + + async remove(key: string): Promise { + const fetchUrl = await this.getFetchUrl(key); + + await this.fetchApi.fetch(fetchUrl, { + method: 'DELETE', + }); + + this.notifyChanges({ + key, + presence: 'absent', + }); + } + + async set(key: string, data: T): Promise { + const fetchUrl = await this.getFetchUrl(key); + const body = JSON.stringify({ value: JSON.stringify(data) }); + + const response = await this.fetchApi.fetch(fetchUrl, { + method: 'PUT', + body, + }); + + const { value } = await response.json(); + + this.notifyChanges({ + key, + value: JSON.parse(value), + presence: 'present', + }); + } + + observe$( + key: string, + ): Observable> { + return this.observable.filter(({ key: messageKey }) => messageKey === key); + } + + snapshot(key: string): StorageValueSnapshot { + // trigger a reload + this.get(key).then(snapshot => this.notifyChanges(snapshot)); + + return { + key, + presence: 'unknown', + }; + } + + private async get( + key: string, + ): Promise> { + try { + const fetchUrl = await this.getFetchUrl(key); + const response = await this.fetchApi.fetch(fetchUrl); + + if (response.status === 404) { + throw new NotFoundError( + `Setting '${key}' is not set in bucket '${this.namespace}'`, + ); + } else if (!response.ok) { + throw new Error( + `Unable to fetch '${key}' from bucket '${this.namespace}'`, + ); + } + + const { value: rawValue } = await response.json(); + const value = JSON.parse(rawValue, (_key, val) => { + if (typeof val === 'object' && val !== null) { + Object.freeze(val); + } + return val; + }); + + return { + key, + presence: 'present', + value, + }; + } catch (error) { + // NotFoundError shouldn't be recorded + if (error && !(error instanceof NotFoundError)) { + this.errorApi.post(error); + } + + return { + key, + presence: 'absent', + value: undefined, + }; + } + } + + private async getFetchUrl(key: string) { + const baseUrl = await this.discoveryApi.getBaseUrl('user-settings'); + const encodedNamespace = encodeURIComponent(this.namespace); + const encodedKey = encodeURIComponent(key); + return `${baseUrl}/${encodedNamespace}/${encodedKey}`; + } + + private async notifyChanges(snapshot: StorageValueSnapshot) { + for (const subscription of this.subscribers) { + subscription.next(snapshot); + } + } +} diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts index 2f941381fd..70a8c9cbe1 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts @@ -15,3 +15,4 @@ */ export { WebStorage } from './WebStorage'; +export { PersistentStorage } from './PersistentStorage'; diff --git a/plugins/user-settings-backend/.eslintrc.js b/plugins/user-settings-backend/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/user-settings-backend/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/user-settings-backend/README.md b/plugins/user-settings-backend/README.md new file mode 100644 index 0000000000..05a8c15c6d --- /dev/null +++ b/plugins/user-settings-backend/README.md @@ -0,0 +1,104 @@ +# User settings backend + +This backend allows to save user specific settings. All requests need to be +authorized, as the user identifier (`userEntityRef`) is resolved using the +authorization token. + +## Setup backend + +1. Install the backend plugin: + +```bash +# From your Backstage root directory +yarn --cwd packages/backend add @backstage/plugin-user-settings-backend +``` + +1. Configure the routes by adding a new `userSettings.ts` file in + `packages/backend/src/plugins/`: + +```ts +// packages/backend/src/plugins/userSettings.ts +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { + createRouter, + createUserSettingsStore, +} from '@backstage/plugin-user-settings-backend'; +import { Router } from 'express'; + +import { PluginEnvironment } from '../types'; + +export default async function createPlugin({ + database, + discovery, +}: PluginEnvironment): Promise { + const identity = IdentityClient.create({ + discovery, + issuer: await discovery.getExternalBaseUrl('auth'), + }); + + return await createRouter({ + userSettingsStore: await createUserSettingsStore(database), + identity, + }); +} +``` + +3. Add the new routes to your backend by modifying the + `packages/backend/src/index.ts`: + +```diff +// packages/backend/src/index.ts ++ import userSettings from './plugins/userSettings'; +async function main() { ++ const userSettingsEnv = useHotMemoize(module, () => ++ createEnv('userSettings'), ++ ); + const apiRouter = Router(); ++ apiRouter.use('/user-settings', await userSettings(userSettingsEnv)); +} +``` + +## Setup app + +To make use of the user settings backend, replace the `WebStorage` with the +`PersistentStorage` by using the `storageApiRef`. + +```diff +// packages/app/src/apis.ts +import { + AnyApiFactory, + createApiFactory, ++ discoveryApiRef, ++ fetchApiRef + errorApiRef, ++ storageApiRef, +} from '@backstage/core-plugin-api'; ++ import { PersistentStorage } from '@backstage/core-app-api'; + +export const apis: AnyApiFactory[] = [ ++ createApiFactory({ ++ api: storageApiRef, ++ deps: { ++ discoveryApi: discoveryApiRef, ++ errorApi: errorApiRef, ++ fetchApi: fetchApiRef, ++ }, ++ factory: ({ discoveryApi, errorApi, fetchApi }) => ++ PersistentStorage.create({ discoveryApi, errorApi, fetchApi }), ++ }), +]; +``` + +## Development + +Use `yarn start` to start the local dev environment. To simplify the access to +the API, the token will automatically be set to `user:default/john_doe`. + +You can change the user by setting a custom `Authorization` header. To keep +things simple, the raw `Bearer` value will directly be used as user. + +_Example:_ + +```bash +curl --request GET 'http://localhost:7007/user-settings' --header 'Authorization: Bearer user:default/custom-user' +``` diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md new file mode 100644 index 0000000000..b3b40970c9 --- /dev/null +++ b/plugins/user-settings-backend/api-report.md @@ -0,0 +1,177 @@ +## API Report File for "@backstage/plugin-user-settings-backend" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import express from 'express'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { Knex } from 'knex'; +import { PluginDatabaseManager } from '@backstage/backend-common'; + +// @public +export function createRouter( + options: RouterOptions, +): Promise; + +// @public (undocumented) +export function createUserSettingsStore( + database: PluginDatabaseManager, +): Promise; + +// @public +export class DatabaseUserSettingsStore + implements UserSettingsStore +{ + // (undocumented) + static create(knex: Knex): Promise; + // (undocumented) + delete( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + }, + ): Promise; + // (undocumented) + deleteAll( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + }, + ): Promise; + // (undocumented) + deleteBucket( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + bucket: string; + }, + ): Promise; + // (undocumented) + get( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + }, + ): Promise; + // (undocumented) + getAll( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + }, + ): Promise[]>; + // (undocumented) + getBucket( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + bucket: string; + }, + ): Promise; + // (undocumented) + set( + tx: Knex.Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }, + ): Promise; + // (undocumented) + transaction(fn: (tx: Knex.Transaction) => Promise): Promise; +} + +// @public (undocumented) +export type RawDbUserSettingsRow = { + user_entity_ref: string; + bucket: string; + key: string; + value: string; +}; + +// @public (undocumented) +export interface RouterOptions { + // (undocumented) + identity: IdentityClient; + // (undocumented) + userSettingsStore: UserSettingsStore; +} + +// @public (undocumented) +export type UserSetting = { + bucket: string; + key: string; + value: string; +}; + +// @public +export interface UserSettingsStore { + // (undocumented) + delete( + tx: Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + }, + ): Promise; + // (undocumented) + deleteAll( + tx: Transaction, + opts: { + userEntityRef: string; + }, + ): Promise; + // (undocumented) + deleteBucket( + tx: Transaction, + opts: { + userEntityRef: string; + bucket: string; + }, + ): Promise; + // (undocumented) + get( + tx: Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + }, + ): Promise; + // (undocumented) + getAll( + tx: Transaction, + opts: { + userEntityRef: string; + }, + ): Promise; + // (undocumented) + getBucket( + tx: Transaction, + opts: { + userEntityRef: string; + bucket: string; + }, + ): Promise; + // (undocumented) + set( + tx: Transaction, + opts: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }, + ): Promise; + // (undocumented) + transaction(fn: (tx: Transaction) => Promise): Promise; +} + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/user-settings-backend/migrations/20220824183000_init.js b/plugins/user-settings-backend/migrations/20220824183000_init.js new file mode 100644 index 0000000000..688d8495b5 --- /dev/null +++ b/plugins/user-settings-backend/migrations/20220824183000_init.js @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.createTable('user_settings', table => { + table.comment('The table of user related settings'); + + table + .text('user_entity_ref') + .notNullable() + .comment('The entityRef of the user'); + table.text('bucket').notNullable().comment('Name of the bucket'); + table.text('key').notNullable().comment('Key of a bucket value'); + table.text('value').notNullable().comment('The value'); + + table.primary(['user_entity_ref', 'bucket', 'key']); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('user_settings'); +}; diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json new file mode 100644 index 0000000000..f20180cac3 --- /dev/null +++ b/plugins/user-settings-backend/package.json @@ -0,0 +1,52 @@ +{ + "name": "@backstage/plugin-user-settings-backend", + "description": "The Backstage backend plugin to manage user settings", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "backstage": { + "role": "backend-plugin" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/user-settings-backend" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean" + }, + "dependencies": { + "@backstage/backend-common": "^0.15.1-next.1", + "@backstage/catalog-model": "^1.1.0", + "@backstage/errors": "^1.1.0", + "@backstage/plugin-auth-node": "^0.2.5-next.1", + "@types/express": "^4.17.6", + "express": "^4.17.1", + "express-promise-router": "^4.1.0", + "knex": "^2.0.0", + "winston": "^3.2.1", + "yn": "^4.0.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "^0.1.28-next.1", + "@backstage/cli": "^0.19.0-next.1", + "@types/supertest": "^2.0.8", + "supertest": "^6.1.3" + }, + "files": [ + "dist", + "migrations" + ] +} diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts new file mode 100644 index 0000000000..717707f034 --- /dev/null +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -0,0 +1,373 @@ +/* + * 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 { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { Knex } from 'knex'; + +import { + DatabaseUserSettingsStore, + RawDbUserSettingsRow, +} from './DatabaseUserSettingsStore'; + +jest.setTimeout(60_000); + +const databases = TestDatabases.create({ + ids: ['POSTGRES_13', 'SQLITE_3'], +}); + +async function createStore(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + return { + knex, + storage: await DatabaseUserSettingsStore.create(knex), + }; +} + +describe.each(databases.eachSupportedId())( + 'DatabaseUserSettingsStore (%s)', + databaseId => { + let storage: DatabaseUserSettingsStore; + let knex: Knex; + + beforeAll(async () => { + ({ storage, knex } = await createStore(databaseId)); + }); + + afterEach(async () => { + jest.resetAllMocks(); + + await knex('user_settings').del(); + }); + + const insert = (data: RawDbUserSettingsRow[]) => + knex('user_settings').insert(data); + const query = () => + knex('user_settings') + .orderBy('user_entity_ref') + .select(); + + describe('getAll', () => { + it('should return empty user settings', async () => { + expect( + await storage.transaction(tx => + storage.getAll(tx, { userEntityRef: 'user-1' }), + ), + ).toEqual([]); + }); + + it('should return all user settings', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-b', + value: 'value-b', + }, + { + user_entity_ref: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + expect( + await storage.transaction(tx => + storage.getAll(tx, { userEntityRef: 'user-1' }), + ), + ).toEqual([ + { bucket: 'bucket-a', key: 'key-a', value: 'value-a' }, + { bucket: 'bucket-a', key: 'key-b', value: 'value-b' }, + { bucket: 'bucket-c', key: 'key-c', value: 'value-c' }, + ]); + }); + }); + + describe('deleteAll', () => { + it('should delete all user settings', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + await storage.transaction(tx => + storage.deleteAll(tx, { userEntityRef: 'user-1' }), + ); + + expect(await query()).toEqual([ + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + }); + }); + + describe('getBucket', () => { + it('should return an empty bucket', async () => { + expect( + await storage.transaction(tx => + storage.getBucket(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-c', + }), + ), + ).toEqual([]); + }); + + it('should return the settings of the bucket', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + expect( + await storage.transaction(tx => + storage.getBucket(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + }), + ), + ).toEqual([{ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }]); + }); + }); + + describe('deleteBucket', () => { + it('should delete a bucket', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + await storage.transaction(tx => + storage.deleteBucket(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + }), + ); + + expect(await query()).toEqual([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + }); + }); + + describe('get', () => { + it('should throw an error', async () => { + await expect(() => + storage.transaction(tx => + storage.get(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), + ), + ).rejects.toThrow(`Unable to find 'key-c' in bucket 'bucket-c'`); + }); + + it('should return the setting', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + expect( + await storage.transaction(tx => + storage.get(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }), + ), + ).toEqual({ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }); + }); + }); + + describe('set', () => { + it('should insert a new setting', async () => { + await storage.transaction(tx => + storage.set(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }), + ); + + expect(await query()).toEqual([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + ]); + }); + + it('should overwrite an existing setting', async () => { + await storage.transaction(tx => + storage.set(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }), + ); + + await storage.transaction(tx => + storage.set(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-b', + }), + ); + + expect(await query()).toEqual([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-b', + }, + ]); + }); + }); + + describe('delete', () => { + it('should not throw an error if the entry does not exist', async () => { + await expect(() => + storage.transaction(tx => + storage.delete(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), + ), + ).not.toThrow(); + }); + + it('should return the setting', async () => { + await insert([ + { + user_entity_ref: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }, + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + + await storage.transaction(tx => + storage.delete(tx, { + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }), + ); + expect(await query()).toEqual([ + { + user_entity_ref: 'user-2', + bucket: 'bucket-c', + key: 'key-c', + value: 'value-c', + }, + ]); + }); + }); + }, +); diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts new file mode 100644 index 0000000000..fd24a6f3e5 --- /dev/null +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -0,0 +1,143 @@ +/* + * 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 { resolvePackagePath } from '@backstage/backend-common'; +import { NotFoundError } from '@backstage/errors'; +import { Knex } from 'knex'; + +import { type UserSetting, UserSettingsStore } from './UserSettingsStore'; + +const migrationsDir = resolvePackagePath( + '@backstage/plugin-user-settings-backend', + 'migrations', +); + +/** + * @public + */ +export type RawDbUserSettingsRow = { + user_entity_ref: string; + bucket: string; + key: string; + value: string; +}; + +/** + * Store to manage the user settings. + * + * @public + */ +export class DatabaseUserSettingsStore + implements UserSettingsStore +{ + static async create(knex: Knex): Promise { + await knex.migrate.latest({ + directory: migrationsDir, + }); + return new DatabaseUserSettingsStore(knex); + } + + private constructor(private readonly db: Knex) {} + + async getAll(tx: Knex.Transaction, opts: { userEntityRef: string }) { + const settings = await tx('user_settings') + .where({ user_entity_ref: opts.userEntityRef }) + .select('bucket', 'key', 'value'); + + return settings; + } + + async deleteAll( + tx: Knex.Transaction, + opts: { userEntityRef: string }, + ): Promise { + await tx('user_settings') + .where({ user_entity_ref: opts.userEntityRef }) + .delete(); + } + + async getBucket( + tx: Knex.Transaction, + opts: { userEntityRef: string; bucket: string }, + ): Promise { + const settings = await tx('user_settings') + .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) + .select(['bucket', 'key', 'value']); + + return settings; + } + + async deleteBucket( + tx: Knex.Transaction, + opts: { userEntityRef: string; bucket: string }, + ): Promise { + await tx('user_settings') + .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) + .delete(); + } + + async get( + tx: Knex.Transaction, + opts: { userEntityRef: string; bucket: string; key: string }, + ): Promise { + const setting = await tx('user_settings') + .where({ + user_entity_ref: opts.userEntityRef, + bucket: opts.bucket, + key: opts.key, + }) + .select(['bucket', 'key', 'value']); + + if (!setting.length) { + throw new NotFoundError( + `Unable to find '${opts.key}' in bucket '${opts.bucket}'`, + ); + } + + return setting[0]; + } + + async set( + tx: Knex.Transaction, + opts: { userEntityRef: string; bucket: string; key: string; value: string }, + ): Promise { + await tx('user_settings') + .insert({ + user_entity_ref: opts.userEntityRef, + bucket: opts.bucket, + key: opts.key, + value: opts.value, + }) + .onConflict(['user_entity_ref', 'bucket', 'key']) + .merge({ value: opts.value }); + } + + async delete( + tx: Knex.Transaction, + opts: { userEntityRef: string; bucket: string; key: string }, + ): Promise { + await tx('user_settings') + .where({ + user_entity_ref: opts.userEntityRef, + bucket: opts.bucket, + key: opts.key, + }) + .delete(); + } + + async transaction(fn: (tx: Knex.Transaction) => Promise) { + return await this.db.transaction(fn); + } +} diff --git a/plugins/user-settings-backend/src/database/UserSettingsStore.ts b/plugins/user-settings-backend/src/database/UserSettingsStore.ts new file mode 100644 index 0000000000..b86673270f --- /dev/null +++ b/plugins/user-settings-backend/src/database/UserSettingsStore.ts @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/** + * @public + */ +export type UserSetting = { + bucket: string; + key: string; + value: string; +}; + +/** + * Store definition for the user settings. + * + * @public + */ +export interface UserSettingsStore { + transaction(fn: (tx: Transaction) => Promise): Promise; + + get( + tx: Transaction, + opts: { userEntityRef: string; bucket: string; key: string }, + ): Promise; + + set( + tx: Transaction, + opts: { userEntityRef: string; bucket: string; key: string; value: string }, + ): Promise; + + delete( + tx: Transaction, + opts: { userEntityRef: string; bucket: string; key: string }, + ): Promise; + + getBucket( + tx: Transaction, + opts: { userEntityRef: string; bucket: string }, + ): Promise; + + deleteBucket( + tx: Transaction, + opts: { userEntityRef: string; bucket: string }, + ): Promise; + + getAll( + tx: Transaction, + opts: { userEntityRef: string }, + ): Promise; + + deleteAll(tx: Transaction, opts: { userEntityRef: string }): Promise; +} diff --git a/plugins/user-settings-backend/src/database/index.ts b/plugins/user-settings-backend/src/database/index.ts new file mode 100644 index 0000000000..23023ceb2d --- /dev/null +++ b/plugins/user-settings-backend/src/database/index.ts @@ -0,0 +1,20 @@ +/* + * 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 { + DatabaseUserSettingsStore, + type RawDbUserSettingsRow, +} from './DatabaseUserSettingsStore'; +export type { UserSettingsStore, UserSetting } from './UserSettingsStore'; diff --git a/plugins/user-settings-backend/src/index.ts b/plugins/user-settings-backend/src/index.ts new file mode 100644 index 0000000000..9d9fe923e4 --- /dev/null +++ b/plugins/user-settings-backend/src/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 * from './service'; +export * from './database'; diff --git a/plugins/user-settings-backend/src/run.ts b/plugins/user-settings-backend/src/run.ts new file mode 100644 index 0000000000..a1ba29a339 --- /dev/null +++ b/plugins/user-settings-backend/src/run.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 { getRootLogger } from '@backstage/backend-common'; +import yn from 'yn'; + +import { startStandaloneServer } from './service/standaloneServer'; + +const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 7007; +const enableCors = yn(process.env.PLUGIN_CORS, { default: false }); +const logger = getRootLogger(); + +startStandaloneServer({ port, enableCors, logger }).catch(err => { + logger.error(err); + process.exit(1); +}); + +process.on('SIGINT', () => { + logger.info('CTRL+C pressed; exiting.'); + process.exit(0); +}); diff --git a/plugins/user-settings-backend/src/service/index.ts b/plugins/user-settings-backend/src/service/index.ts new file mode 100644 index 0000000000..5f4020dc68 --- /dev/null +++ b/plugins/user-settings-backend/src/service/index.ts @@ -0,0 +1,20 @@ +/* + * 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 { + createRouter, + createUserSettingsStore, + type RouterOptions, +} from './router'; diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts new file mode 100644 index 0000000000..ba23ad11c0 --- /dev/null +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -0,0 +1,319 @@ +/* + * 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 { AuthenticationError } from '@backstage/errors'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import express from 'express'; +import request from 'supertest'; + +import { UserSettingsStore } from '../database'; +import { createRouter } from './router'; + +describe('createRouter', () => { + const userSettingsStore: jest.Mocked> = { + transaction: jest.fn(), + deleteAll: jest.fn(), + getAll: jest.fn(), + getBucket: jest.fn(), + deleteBucket: jest.fn(), + get: jest.fn(), + set: jest.fn(), + delete: jest.fn(), + }; + const authenticateMock = jest.fn(); + const identityClient: jest.Mocked> = { + authenticate: authenticateMock, + }; + + let app: express.Express; + + beforeEach(async () => { + userSettingsStore.transaction.mockImplementation(fn => fn('tx')); + + const router = await createRouter({ + userSettingsStore, + identity: identityClient as IdentityClient, + }); + + app = express().use(router); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('GET /', () => { + it('returns ok', async () => { + const settings = [ + { bucket: 'a', key: 'a', value: 'a' }, + { bucket: 'b', key: 'b', value: 'b' }, + ]; + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.getAll.mockResolvedValue(settings); + + const responses = await request(app) + .get('/') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(200); + expect(responses.body).toEqual(settings); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.getAll).toBeCalledTimes(1); + expect(userSettingsStore.getAll).toBeCalledWith('tx', { + userEntityRef: 'user-1', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).get('/'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.getAll).not.toHaveBeenCalled(); + }); + + it('returns an error if the token is not valid', async () => { + authenticateMock.mockRejectedValue( + new AuthenticationError('Invalid token'), + ); + + const responses = await request(app) + .get('/') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.getAll).not.toHaveBeenCalled(); + }); + }); + + describe('DELETE /', () => { + it('returns ok', async () => { + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.deleteAll.mockResolvedValue(); + + const responses = await request(app) + .delete('/') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(204); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.deleteAll).toBeCalledTimes(1); + expect(userSettingsStore.deleteAll).toBeCalledWith('tx', { + userEntityRef: 'user-1', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).delete('/'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.getAll).not.toHaveBeenCalled(); + }); + }); + + describe('GET /:bucket', () => { + it('returns ok', async () => { + const settings = [ + { bucket: 'my-bucket', key: 'a', value: 'a' }, + { bucket: 'my-bucket', key: 'b', value: 'b' }, + ]; + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.getBucket.mockResolvedValue(settings); + + const responses = await request(app) + .get('/my-bucket') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(200); + expect(responses.body).toEqual(settings); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.getBucket).toBeCalledTimes(1); + expect(userSettingsStore.getBucket).toBeCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).get('/my-bucket'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.getBucket).not.toHaveBeenCalled(); + }); + }); + + describe('DELETE /:bucket', () => { + it('returns ok', async () => { + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.deleteBucket.mockResolvedValue(); + + const responses = await request(app) + .delete('/my-bucket') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(204); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.deleteBucket).toBeCalledTimes(1); + expect(userSettingsStore.deleteBucket).toBeCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).delete('/my-bucket'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.deleteBucket).not.toHaveBeenCalled(); + }); + }); + + describe('GET /:bucket/:key', () => { + it('returns ok', async () => { + const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.get.mockResolvedValue(setting); + + const responses = await request(app) + .get('/my-bucket/my-key') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(200); + expect(responses.body).toEqual(setting); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.get).toBeCalledTimes(1); + expect(userSettingsStore.get).toBeCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + key: 'my-key', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).get('/my-bucket/my-key'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.get).not.toHaveBeenCalled(); + }); + }); + + describe('DELETE /:bucket/:key', () => { + it('returns ok', async () => { + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.delete.mockResolvedValue(); + + const responses = await request(app) + .delete('/my-bucket/my-key') + .set('Authorization', 'Bearer foo'); + + expect(responses.status).toEqual(204); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.delete).toBeCalledTimes(1); + expect(userSettingsStore.delete).toBeCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + key: 'my-key', + }); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).delete('/my-bucket/my-key'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.delete).not.toHaveBeenCalled(); + }); + }); + + describe('PUT /:bucket/:key', () => { + it('returns ok', async () => { + const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + userSettingsStore.set.mockResolvedValue(); + userSettingsStore.get.mockResolvedValue(setting); + + const responses = await request(app) + .put('/my-bucket/my-key') + .set('Authorization', 'Bearer foo') + .send({ value: 'a' }); + + expect(responses.status).toEqual(200); + expect(responses.body).toEqual(setting); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.set).toBeCalledTimes(1); + expect(userSettingsStore.set).toHaveBeenCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + key: 'my-key', + value: 'a', + }); + expect(userSettingsStore.get).toBeCalledTimes(1); + expect(userSettingsStore.get).toBeCalledWith('tx', { + userEntityRef: 'user-1', + bucket: 'my-bucket', + key: 'my-key', + }); + }); + + it('returns an error if the value is not a string', async () => { + authenticateMock.mockResolvedValue({ + identity: { userEntityRef: 'user-1' }, + }); + + const responses = await request(app) + .put('/my-bucket/my-key') + .set('Authorization', 'Bearer foo') + .send({ value: { invalid: 'because not a string' } }); + + expect(responses.status).toEqual(400); + + expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(userSettingsStore.set).not.toHaveBeenCalled(); + }); + + it('returns an error if the Authorization header is missing', async () => { + const responses = await request(app).get('/my-bucket/my-key'); + + expect(responses.status).toEqual(401); + expect(userSettingsStore.get).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts new file mode 100644 index 0000000000..a715433dcb --- /dev/null +++ b/plugins/user-settings-backend/src/service/router.ts @@ -0,0 +1,168 @@ +/* + * 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 { PluginDatabaseManager, errorHandler } from '@backstage/backend-common'; +import { AuthenticationError, InputError } from '@backstage/errors'; +import { + getBearerTokenFromAuthorizationHeader, + IdentityClient, +} from '@backstage/plugin-auth-node'; +import express, { Request } from 'express'; +import Router from 'express-promise-router'; + +import { DatabaseUserSettingsStore, UserSettingsStore } from '../database'; + +/** + * @public + */ +export async function createUserSettingsStore(database: PluginDatabaseManager) { + return await DatabaseUserSettingsStore.create(await database.getClient()); +} + +/** + * @public + */ +export interface RouterOptions { + userSettingsStore: UserSettingsStore; + identity: IdentityClient; +} + +/** + * Create the user settings backend routes. + * + * @public + */ +export async function createRouter( + options: RouterOptions, +): Promise { + const { userSettingsStore, identity } = options; + const router = Router(); + router.use(express.json()); + + /** + * Helper method to extract the userEntityRef from the request. + */ + const getUserEntityRef = async (req: Request): Promise => { + const token = getBearerTokenFromAuthorizationHeader( + req.header('authorization'), + ); + + if (!token) { + throw new AuthenticationError(`Missing token in 'authorization' header`); + } + + // throws an AuthenticationError in case the token is invalid + const user = await identity.authenticate(token); + + return user.identity.userEntityRef; + }; + + // get all user related settings + router.get('/', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + + const settings = await userSettingsStore.transaction(tx => + userSettingsStore.getAll(tx, { userEntityRef }), + ); + + res.json(settings); + }); + + // remove all user related settings + router.delete('/', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + + await userSettingsStore.transaction(tx => + userSettingsStore.deleteAll(tx, { userEntityRef }), + ); + + res.send(204).end(); + }); + + // get a single bucket + router.get('/:bucket', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + const { bucket } = req.params; + + const settings = await userSettingsStore.transaction(tx => + userSettingsStore.getBucket(tx, { userEntityRef, bucket }), + ); + + res.json(settings); + }); + + // delete a whole bucket + router.delete('/:bucket', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + const { bucket } = req.params; + + await userSettingsStore.transaction(tx => + userSettingsStore.deleteBucket(tx, { userEntityRef, bucket }), + ); + + res.status(204).end(); + }); + + // get a single value + router.get('/:bucket/:key', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + const { bucket, key } = req.params; + + const setting = await userSettingsStore.transaction(tx => + userSettingsStore.get(tx, { userEntityRef, bucket, key }), + ); + + res.json(setting); + }); + + // set a single value + router.put('/:bucket/:key', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + const { bucket, key } = req.params; + const { value } = req.body; + + if (typeof value !== 'string') { + throw new InputError('Value must be a string'); + } + + const setting = await userSettingsStore.transaction(async tx => { + await userSettingsStore.set(tx, { + userEntityRef, + bucket, + key, + value, + }); + return userSettingsStore.get(tx, { userEntityRef, bucket, key }); + }); + + res.json(setting); + }); + + // get a single value + router.delete('/:bucket/:key', async (req, res) => { + const userEntityRef = await getUserEntityRef(req); + const { bucket, key } = req.params; + + await userSettingsStore.transaction(tx => + userSettingsStore.delete(tx, { userEntityRef, bucket, key }), + ); + + res.send(204).end(); + }); + + router.use(errorHandler()); + + return router; +} diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts new file mode 100644 index 0000000000..39ef0ba098 --- /dev/null +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -0,0 +1,82 @@ +/* + * 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 { Server } from 'http'; + +import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common'; +import Knex from 'knex'; +import { Logger } from 'winston'; + +import { DatabaseUserSettingsStore } from '../database'; +import { createRouter } from './router'; +import { IdentityClient } from '@backstage/plugin-auth-node'; +import { Router } from 'express'; + +export interface ServerOptions { + port: number; + enableCors: boolean; + logger: Logger; +} + +export async function startStandaloneServer( + options: ServerOptions, +): Promise { + const logger = options.logger.child({ service: 'storage-backend' }); + + const database = useHotMemoize(module, () => { + return Knex({ + client: 'better-sqlite3', + connection: ':memory:', + useNullAsDefault: true, + }); + }); + + logger.debug('Starting application server...'); + + const identityMock = { + authenticate: async token => ({ + identity: { userEntityRef: token ?? 'user:default/john_doe' }, + }), + } as IdentityClient; + + const router = await createRouter({ + userSettingsStore: await DatabaseUserSettingsStore.create(database), + identity: identityMock, + }); + + // set a custom authorization header to simplify the development + const authWrapper = Router(); + authWrapper.use((req, _res, next) => { + req.headers.authorization = + req.headers.authorization ?? 'Bearer user:default/john_doe'; + next(); + }); + authWrapper.use(router); + + let service = createServiceBuilder(module) + .setPort(options.port) + .addRouter('/user-settings', authWrapper); + + if (options.enableCors) { + service = service.enableCors({ origin: 'http://localhost:3000' }); + } + + return await service.start().catch(err => { + logger.error(err); + process.exit(1); + }); +} + +module.hot?.accept(); diff --git a/plugins/user-settings-backend/src/setupTests.ts b/plugins/user-settings-backend/src/setupTests.ts new file mode 100644 index 0000000000..8b9b6bd586 --- /dev/null +++ b/plugins/user-settings-backend/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export {}; diff --git a/yarn.lock b/yarn.lock index afe89bf424..a51757dcde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2855,7 +2855,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-common@^0.15.1-next.3, @backstage/backend-common@workspace:packages/backend-common": +"@backstage/backend-common@^0.15.1-next.1, @backstage/backend-common@^0.15.1-next.3, @backstage/backend-common@workspace:packages/backend-common": version: 0.0.0-use.local resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: @@ -2991,7 +2991,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-test-utils@^0.1.28-next.3, @backstage/backend-test-utils@workspace:packages/backend-test-utils": +"@backstage/backend-test-utils@^0.1.28-next.1, @backstage/backend-test-utils@^0.1.28-next.3, @backstage/backend-test-utils@workspace:packages/backend-test-utils": version: 0.0.0-use.local resolution: "@backstage/backend-test-utils@workspace:packages/backend-test-utils" dependencies: @@ -3291,6 +3291,8 @@ __metadata: "@backstage/cli": ^0.19.0-next.3 "@backstage/config": ^1.0.2-next.0 "@backstage/core-plugin-api": ^1.0.6-next.3 + "@backstage/errors": ^1.1.0 + "@backstage/plugin-permission-common": ^0.6.4-next.0 "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 @@ -4027,7 +4029,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-node@^0.2.5-next.3, @backstage/plugin-auth-node@workspace:plugins/auth-node": +"@backstage/plugin-auth-node@^0.2.5-next.1, @backstage/plugin-auth-node@^0.2.5-next.3, @backstage/plugin-auth-node@workspace:plugins/auth-node": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-node@workspace:plugins/auth-node" dependencies: @@ -7310,6 +7312,27 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend": + version: 0.0.0-use.local + resolution: "@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend" + dependencies: + "@backstage/backend-common": ^0.15.1-next.1 + "@backstage/backend-test-utils": ^0.1.28-next.1 + "@backstage/catalog-model": ^1.1.0 + "@backstage/cli": ^0.19.0-next.1 + "@backstage/errors": ^1.1.0 + "@backstage/plugin-auth-node": ^0.2.5-next.1 + "@types/express": ^4.17.6 + "@types/supertest": ^2.0.8 + express: ^4.17.1 + express-promise-router: ^4.1.0 + knex: ^2.0.0 + supertest: ^6.1.3 + winston: ^3.2.1 + yn: ^4.0.0 + languageName: unknown + linkType: soft + "@backstage/plugin-user-settings@^0.4.8-next.3, @backstage/plugin-user-settings@workspace:plugins/user-settings": version: 0.0.0-use.local resolution: "@backstage/plugin-user-settings@workspace:plugins/user-settings" From 32fa6ca2d8a4912cd6d1b7a228fc20bad0f5ce4d Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 10:30:02 +0200 Subject: [PATCH 42/95] fix: change imports Signed-off-by: Dominik Schwank --- packages/core-app-api/package.json | 1 - .../implementations/StorageApi/PersistentStorage.test.ts | 8 ++++++-- yarn.lock | 1 - 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 632c429361..e1c24997ac 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -35,7 +35,6 @@ "@backstage/config": "^1.0.2-next.0", "@backstage/core-plugin-api": "^1.0.6-next.3", "@backstage/errors": "^1.1.0", - "@backstage/plugin-permission-common": "^0.6.4-next.0", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts index 6cea8dde5b..dfa0008e32 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts @@ -15,8 +15,12 @@ */ import { PersistentStorage } from './PersistentStorage'; -import { ErrorApi, FetchApi, StorageApi } from '@backstage/core-plugin-api'; -import { DiscoveryApi } from '@backstage/plugin-permission-common'; +import { + ErrorApi, + FetchApi, + StorageApi, + DiscoveryApi, +} from '@backstage/core-plugin-api'; import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; import { rest } from 'msw'; diff --git a/yarn.lock b/yarn.lock index a51757dcde..9df599d106 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3292,7 +3292,6 @@ __metadata: "@backstage/config": ^1.0.2-next.0 "@backstage/core-plugin-api": ^1.0.6-next.3 "@backstage/errors": ^1.1.0 - "@backstage/plugin-permission-common": ^0.6.4-next.0 "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 From 3250830e6ec3b8006bbd86e252634cf0c9e6fde9 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 10:31:22 +0200 Subject: [PATCH 43/95] feat: use string in DB instead of text Signed-off-by: Dominik Schwank --- .../user-settings-backend/migrations/20220824183000_init.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/user-settings-backend/migrations/20220824183000_init.js b/plugins/user-settings-backend/migrations/20220824183000_init.js index 688d8495b5..a519969a98 100644 --- a/plugins/user-settings-backend/migrations/20220824183000_init.js +++ b/plugins/user-settings-backend/migrations/20220824183000_init.js @@ -22,11 +22,11 @@ exports.up = async function up(knex) { table.comment('The table of user related settings'); table - .text('user_entity_ref') + .string('user_entity_ref') .notNullable() .comment('The entityRef of the user'); - table.text('bucket').notNullable().comment('Name of the bucket'); - table.text('key').notNullable().comment('Key of a bucket value'); + table.string('bucket').notNullable().comment('Name of the bucket'); + table.string('key').notNullable().comment('Key of a bucket value'); table.text('value').notNullable().comment('The value'); table.primary(['user_entity_ref', 'bucket', 'key']); From 81f0945f6e724427abd522f6f74544d26e471a3a Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 10:31:45 +0200 Subject: [PATCH 44/95] fix: change initial version to 0.0.0 Signed-off-by: Dominik Schwank --- plugins/user-settings-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index f20180cac3..41178d49b8 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.1.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 1e12c7f5f188cdf221d876e2b6e4faf6908d9b83 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 11:03:32 +0200 Subject: [PATCH 45/95] feat: support skip migration Signed-off-by: Dominik Schwank --- plugins/user-settings-backend/api-report.md | 9 +++----- .../DatabaseUserSettingsStore.test.ts | 11 ++++++++- .../src/database/DatabaseUserSettingsStore.ts | 23 ++++++++++++++----- .../src/service/index.ts | 6 +---- .../src/service/router.ts | 11 ++------- .../src/service/standaloneServer.ts | 4 +++- 6 files changed, 36 insertions(+), 28 deletions(-) diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index b3b40970c9..47e59637d6 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -13,17 +13,14 @@ export function createRouter( options: RouterOptions, ): Promise; -// @public (undocumented) -export function createUserSettingsStore( - database: PluginDatabaseManager, -): Promise; - // @public export class DatabaseUserSettingsStore implements UserSettingsStore { // (undocumented) - static create(knex: Knex): Promise; + static create(options: { + database: PluginDatabaseManager; + }): Promise; // (undocumented) delete( tx: Knex.Transaction, diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts index 717707f034..547beaa6b6 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -29,9 +29,18 @@ const databases = TestDatabases.create({ async function createStore(databaseId: TestDatabaseId) { const knex = await databases.init(databaseId); + const databaseManager = { + getClient: async () => knex, + migrations: { + skip: false, + }, + }; + return { knex, - storage: await DatabaseUserSettingsStore.create(knex), + storage: await DatabaseUserSettingsStore.create({ + database: databaseManager, + }), }; } diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts index fd24a6f3e5..2e2eb6318a 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { resolvePackagePath } from '@backstage/backend-common'; +import { + PluginDatabaseManager, + resolvePackagePath, +} from '@backstage/backend-common'; import { NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; @@ -42,11 +45,19 @@ export type RawDbUserSettingsRow = { export class DatabaseUserSettingsStore implements UserSettingsStore { - static async create(knex: Knex): Promise { - await knex.migrate.latest({ - directory: migrationsDir, - }); - return new DatabaseUserSettingsStore(knex); + static async create(options: { + database: PluginDatabaseManager; + }): Promise { + const { database } = options; + const client = await database.getClient(); + + if (!database.migrations?.skip) { + await client.migrate.latest({ + directory: migrationsDir, + }); + } + + return new DatabaseUserSettingsStore(client); } private constructor(private readonly db: Knex) {} diff --git a/plugins/user-settings-backend/src/service/index.ts b/plugins/user-settings-backend/src/service/index.ts index 5f4020dc68..8f3e084d24 100644 --- a/plugins/user-settings-backend/src/service/index.ts +++ b/plugins/user-settings-backend/src/service/index.ts @@ -13,8 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { - createRouter, - createUserSettingsStore, - type RouterOptions, -} from './router'; +export { createRouter, type RouterOptions } from './router'; diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index a715433dcb..0a8c52b156 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { PluginDatabaseManager, errorHandler } from '@backstage/backend-common'; +import { errorHandler } from '@backstage/backend-common'; import { AuthenticationError, InputError } from '@backstage/errors'; import { getBearerTokenFromAuthorizationHeader, @@ -22,14 +22,7 @@ import { import express, { Request } from 'express'; import Router from 'express-promise-router'; -import { DatabaseUserSettingsStore, UserSettingsStore } from '../database'; - -/** - * @public - */ -export async function createUserSettingsStore(database: PluginDatabaseManager) { - return await DatabaseUserSettingsStore.create(await database.getClient()); -} +import { UserSettingsStore } from '../database'; /** * @public diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 39ef0ba098..1e079f02c0 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -52,7 +52,9 @@ export async function startStandaloneServer( } as IdentityClient; const router = await createRouter({ - userSettingsStore: await DatabaseUserSettingsStore.create(database), + userSettingsStore: await DatabaseUserSettingsStore.create({ + database: { getClient: async () => database }, + }), identity: identityMock, }); From 31a240304444d11e18e3d64f3bef24d877685681 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 11:12:44 +0200 Subject: [PATCH 46/95] feat: use buckets prefix for routes Signed-off-by: Dominik Schwank --- .../StorageApi/PersistentStorage.test.ts | 41 ++++++---- .../StorageApi/PersistentStorage.ts | 2 +- .../src/service/router.test.ts | 76 +++++++++---------- .../src/service/router.ts | 14 ++-- 4 files changed, 71 insertions(+), 62 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts index dfa0008e32..3157395bcf 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts @@ -52,7 +52,7 @@ describe('Persistent Storage API', () => { beforeEach(() => { server.use( - rest.get(`${mockBaseUrl}/`, async (_req, res, ctx) => { + rest.get(`${mockBaseUrl}/buckets/`, async (_req, res, ctx) => { return res(ctx.json([])); }), ); @@ -64,9 +64,12 @@ describe('Persistent Storage API', () => { const storage = createPersistentStorage(); server.use( - rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { - return res(ctx.json({ value: 'a' })); - }), + rest.get( + `${mockBaseUrl}/buckets/:bucket/:key`, + async (_req, res, ctx) => { + return res(ctx.json({ value: 'a' })); + }, + ), ); expect(storage.snapshot('myfakekey').value).toBeUndefined(); @@ -82,7 +85,7 @@ describe('Persistent Storage API', () => { const dummyValue = 'a'; server.use( - rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const body = await req.json(); const data = { value: JSON.stringify(dummyValue) }; expect(body).toEqual(data); @@ -102,7 +105,7 @@ describe('Persistent Storage API', () => { }; server.use( - rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const body = await req.json(); const data = { value: JSON.stringify(dummyValue) }; expect(body).toEqual(data); @@ -122,7 +125,7 @@ describe('Persistent Storage API', () => { const mockData = { hello: 'im a great new value' }; server.use( - rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const body = await req.json(); const data = { value: JSON.stringify(mockData) }; expect(body).toEqual(data); @@ -162,9 +165,12 @@ describe('Persistent Storage API', () => { const selectedKeyNextHandler = jest.fn(); server.use( - rest.delete(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { - return res(ctx.status(204)); - }), + rest.delete( + `${mockBaseUrl}/buckets/:bucket/:key`, + async (_req, res, ctx) => { + return res(ctx.status(204)); + }, + ), ); await new Promise(resolve => { @@ -196,7 +202,7 @@ describe('Persistent Storage API', () => { const selectedKeyNextHandler = jest.fn(); server.use( - rest.put(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const { bucket, key } = req.params; const { value } = await req.json(); @@ -205,7 +211,7 @@ describe('Persistent Storage API', () => { return res(ctx.json({ value })); }), - rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const { bucket, key } = req.params; expect(bucket).toEqual('default.profile/something'); @@ -253,7 +259,7 @@ describe('Persistent Storage API', () => { }); server.use( - rest.get(`${mockBaseUrl}/:bucket/:key`, async (req, res, ctx) => { + rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { const { bucket, key } = req.params; expect(bucket).toEqual('Test.Mock.Thing'); @@ -290,9 +296,12 @@ describe('Persistent Storage API', () => { const data = { foo: 'bar', baz: [{ foo: 'bar' }] }; server.use( - rest.get(`${mockBaseUrl}/:bucket/:key`, async (_req, res, ctx) => { - return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) }))); - }), + rest.get( + `${mockBaseUrl}/buckets/:bucket/:key`, + async (_req, res, ctx) => { + return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) }))); + }, + ), ); await new Promise(resolve => { diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts index 4ebf635cd9..38a986863e 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts @@ -182,7 +182,7 @@ export class PersistentStorage implements StorageApi { const baseUrl = await this.discoveryApi.getBaseUrl('user-settings'); const encodedNamespace = encodeURIComponent(this.namespace); const encodedKey = encodeURIComponent(key); - return `${baseUrl}/${encodedNamespace}/${encodedKey}`; + return `${baseUrl}/buckets/${encodedNamespace}/${encodedKey}`; } private async notifyChanges(snapshot: StorageValueSnapshot) { diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index ba23ad11c0..21aff9f164 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -54,7 +54,7 @@ describe('createRouter', () => { jest.resetAllMocks(); }); - describe('GET /', () => { + describe('GET /buckets/', () => { it('returns ok', async () => { const settings = [ { bucket: 'a', key: 'a', value: 'a' }, @@ -67,21 +67,21 @@ describe('createRouter', () => { userSettingsStore.getAll.mockResolvedValue(settings); const responses = await request(app) - .get('/') + .get('/buckets/') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(200); expect(responses.body).toEqual(settings); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getAll).toBeCalledTimes(1); - expect(userSettingsStore.getAll).toBeCalledWith('tx', { + expect(userSettingsStore.getAll).toHaveBeenCalledTimes(1); + expect(userSettingsStore.getAll).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', }); }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/'); + const responses = await request(app).get('/buckets/'); expect(responses.status).toEqual(401); expect(userSettingsStore.getAll).not.toHaveBeenCalled(); @@ -93,7 +93,7 @@ describe('createRouter', () => { ); const responses = await request(app) - .get('/') + .get('/buckets/') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(401); @@ -101,7 +101,7 @@ describe('createRouter', () => { }); }); - describe('DELETE /', () => { + describe('DELETE /buckets/', () => { it('returns ok', async () => { authenticateMock.mockResolvedValue({ identity: { userEntityRef: 'user-1' }, @@ -110,27 +110,27 @@ describe('createRouter', () => { userSettingsStore.deleteAll.mockResolvedValue(); const responses = await request(app) - .delete('/') + .delete('/buckets/') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(204); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteAll).toBeCalledTimes(1); - expect(userSettingsStore.deleteAll).toBeCalledWith('tx', { + expect(userSettingsStore.deleteAll).toHaveBeenCalledTimes(1); + expect(userSettingsStore.deleteAll).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', }); }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/'); + const responses = await request(app).delete('/buckets/'); expect(responses.status).toEqual(401); expect(userSettingsStore.getAll).not.toHaveBeenCalled(); }); }); - describe('GET /:bucket', () => { + describe('GET /buckets/:bucket', () => { it('returns ok', async () => { const settings = [ { bucket: 'my-bucket', key: 'a', value: 'a' }, @@ -143,29 +143,29 @@ describe('createRouter', () => { userSettingsStore.getBucket.mockResolvedValue(settings); const responses = await request(app) - .get('/my-bucket') + .get('/buckets/my-bucket') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(200); expect(responses.body).toEqual(settings); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getBucket).toBeCalledTimes(1); - expect(userSettingsStore.getBucket).toBeCalledWith('tx', { + expect(userSettingsStore.getBucket).toHaveBeenCalledTimes(1); + expect(userSettingsStore.getBucket).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', }); }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/my-bucket'); + const responses = await request(app).get('/buckets/my-bucket'); expect(responses.status).toEqual(401); expect(userSettingsStore.getBucket).not.toHaveBeenCalled(); }); }); - describe('DELETE /:bucket', () => { + describe('DELETE /buckets/:bucket', () => { it('returns ok', async () => { authenticateMock.mockResolvedValue({ identity: { userEntityRef: 'user-1' }, @@ -174,28 +174,28 @@ describe('createRouter', () => { userSettingsStore.deleteBucket.mockResolvedValue(); const responses = await request(app) - .delete('/my-bucket') + .delete('/buckets/my-bucket') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(204); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteBucket).toBeCalledTimes(1); - expect(userSettingsStore.deleteBucket).toBeCalledWith('tx', { + expect(userSettingsStore.deleteBucket).toHaveBeenCalledTimes(1); + expect(userSettingsStore.deleteBucket).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', }); }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/my-bucket'); + const responses = await request(app).delete('/buckets/my-bucket'); expect(responses.status).toEqual(401); expect(userSettingsStore.deleteBucket).not.toHaveBeenCalled(); }); }); - describe('GET /:bucket/:key', () => { + describe('GET /buckets/:bucket/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; authenticateMock.mockResolvedValue({ @@ -205,15 +205,15 @@ describe('createRouter', () => { userSettingsStore.get.mockResolvedValue(setting); const responses = await request(app) - .get('/my-bucket/my-key') + .get('/buckets/my-bucket/my-key') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(200); expect(responses.body).toEqual(setting); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.get).toBeCalledTimes(1); - expect(userSettingsStore.get).toBeCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledTimes(1); + expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -221,14 +221,14 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/my-bucket/my-key'); + const responses = await request(app).get('/buckets/my-bucket/my-key'); expect(responses.status).toEqual(401); expect(userSettingsStore.get).not.toHaveBeenCalled(); }); }); - describe('DELETE /:bucket/:key', () => { + describe('DELETE /buckets/:bucket/:key', () => { it('returns ok', async () => { authenticateMock.mockResolvedValue({ identity: { userEntityRef: 'user-1' }, @@ -237,14 +237,14 @@ describe('createRouter', () => { userSettingsStore.delete.mockResolvedValue(); const responses = await request(app) - .delete('/my-bucket/my-key') + .delete('/buckets/my-bucket/my-key') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(204); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.delete).toBeCalledTimes(1); - expect(userSettingsStore.delete).toBeCalledWith('tx', { + expect(userSettingsStore.delete).toHaveBeenCalledTimes(1); + expect(userSettingsStore.delete).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -252,14 +252,14 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/my-bucket/my-key'); + const responses = await request(app).delete('/buckets/my-bucket/my-key'); expect(responses.status).toEqual(401); expect(userSettingsStore.delete).not.toHaveBeenCalled(); }); }); - describe('PUT /:bucket/:key', () => { + describe('PUT /buckets/:bucket/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; authenticateMock.mockResolvedValue({ @@ -270,7 +270,7 @@ describe('createRouter', () => { userSettingsStore.get.mockResolvedValue(setting); const responses = await request(app) - .put('/my-bucket/my-key') + .put('/buckets/my-bucket/my-key') .set('Authorization', 'Bearer foo') .send({ value: 'a' }); @@ -278,15 +278,15 @@ describe('createRouter', () => { expect(responses.body).toEqual(setting); expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.set).toBeCalledTimes(1); + expect(userSettingsStore.set).toHaveBeenCalledTimes(1); expect(userSettingsStore.set).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', value: 'a', }); - expect(userSettingsStore.get).toBeCalledTimes(1); - expect(userSettingsStore.get).toBeCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledTimes(1); + expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -299,7 +299,7 @@ describe('createRouter', () => { }); const responses = await request(app) - .put('/my-bucket/my-key') + .put('/buckets/my-bucket/my-key') .set('Authorization', 'Bearer foo') .send({ value: { invalid: 'because not a string' } }); @@ -310,7 +310,7 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/my-bucket/my-key'); + const responses = await request(app).get('/buckets/my-bucket/my-key'); expect(responses.status).toEqual(401); expect(userSettingsStore.get).not.toHaveBeenCalled(); diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index 0a8c52b156..588759c929 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -63,7 +63,7 @@ export async function createRouter( }; // get all user related settings - router.get('/', async (req, res) => { + router.get('/buckets', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const settings = await userSettingsStore.transaction(tx => @@ -74,7 +74,7 @@ export async function createRouter( }); // remove all user related settings - router.delete('/', async (req, res) => { + router.delete('/buckets', async (req, res) => { const userEntityRef = await getUserEntityRef(req); await userSettingsStore.transaction(tx => @@ -85,7 +85,7 @@ export async function createRouter( }); // get a single bucket - router.get('/:bucket', async (req, res) => { + router.get('/buckets/:bucket', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket } = req.params; @@ -97,7 +97,7 @@ export async function createRouter( }); // delete a whole bucket - router.delete('/:bucket', async (req, res) => { + router.delete('/buckets/:bucket', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket } = req.params; @@ -109,7 +109,7 @@ export async function createRouter( }); // get a single value - router.get('/:bucket/:key', async (req, res) => { + router.get('/buckets/:bucket/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; @@ -121,7 +121,7 @@ export async function createRouter( }); // set a single value - router.put('/:bucket/:key', async (req, res) => { + router.put('/buckets/:bucket/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; const { value } = req.body; @@ -144,7 +144,7 @@ export async function createRouter( }); // get a single value - router.delete('/:bucket/:key', async (req, res) => { + router.delete('/buckets/:bucket/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; From 8f7e5a7517ed25d9ff34cb1a37d367698c321885 Mon Sep 17 00:00:00 2001 From: Dominik Schwank Date: Thu, 1 Sep 2022 11:22:42 +0200 Subject: [PATCH 47/95] feat: add keys path support Signed-off-by: Dominik Schwank --- .../StorageApi/PersistentStorage.test.ts | 98 +++++++++++-------- .../StorageApi/PersistentStorage.ts | 2 +- .../src/service/router.test.ts | 26 +++-- .../src/service/router.ts | 6 +- 4 files changed, 78 insertions(+), 54 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts index 3157395bcf..79da01ca41 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts @@ -65,7 +65,7 @@ describe('Persistent Storage API', () => { server.use( rest.get( - `${mockBaseUrl}/buckets/:bucket/:key`, + `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (_req, res, ctx) => { return res(ctx.json({ value: 'a' })); }, @@ -85,13 +85,16 @@ describe('Persistent Storage API', () => { const dummyValue = 'a'; server.use( - rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const body = await req.json(); - const data = { value: JSON.stringify(dummyValue) }; - expect(body).toEqual(data); + rest.put( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(dummyValue) }; + expect(body).toEqual(data); - return res(ctx.json(data)); - }), + return res(ctx.json(data)); + }, + ), ); await storage.set('my-key', dummyValue); @@ -105,13 +108,16 @@ describe('Persistent Storage API', () => { }; server.use( - rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const body = await req.json(); - const data = { value: JSON.stringify(dummyValue) }; - expect(body).toEqual(data); + rest.put( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(dummyValue) }; + expect(body).toEqual(data); - return res(ctx.json(data)); - }), + return res(ctx.json(data)); + }, + ), ); await storage.set('my-key', dummyValue); @@ -125,13 +131,16 @@ describe('Persistent Storage API', () => { const mockData = { hello: 'im a great new value' }; server.use( - rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const body = await req.json(); - const data = { value: JSON.stringify(mockData) }; - expect(body).toEqual(data); + rest.put( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const body = await req.json(); + const data = { value: JSON.stringify(mockData) }; + expect(body).toEqual(data); - return res(ctx.json(data)); - }), + return res(ctx.json(data)); + }, + ), ); await new Promise(resolve => { @@ -166,7 +175,7 @@ describe('Persistent Storage API', () => { server.use( rest.delete( - `${mockBaseUrl}/buckets/:bucket/:key`, + `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (_req, res, ctx) => { return res(ctx.status(204)); }, @@ -202,23 +211,29 @@ describe('Persistent Storage API', () => { const selectedKeyNextHandler = jest.fn(); server.use( - rest.put(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const { bucket, key } = req.params; - const { value } = await req.json(); + rest.put( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const { bucket, key } = req.params; + const { value } = await req.json(); - expect(bucket).toEqual('default.profile.something.deep'); - expect(key).toEqual('test2'); + expect(bucket).toEqual('default.profile.something.deep'); + expect(key).toEqual('test2'); - return res(ctx.json({ value })); - }), - rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const { bucket, key } = req.params; + return res(ctx.json({ value })); + }, + ), + rest.get( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const { bucket, key } = req.params; - expect(bucket).toEqual('default.profile/something'); - expect(key).toEqual('deep/test2'); + expect(bucket).toEqual('default.profile/something'); + expect(key).toEqual('deep/test2'); - return res(ctx.status(404)); - }), + return res(ctx.status(404)); + }, + ), ); // when getting key test2 it will translate to default.profile.something.deep/test2 @@ -259,14 +274,17 @@ describe('Persistent Storage API', () => { }); server.use( - rest.get(`${mockBaseUrl}/buckets/:bucket/:key`, async (req, res, ctx) => { - const { bucket, key } = req.params; + rest.get( + `${mockBaseUrl}/buckets/:bucket/keys/:key`, + async (req, res, ctx) => { + const { bucket, key } = req.params; - expect(bucket).toEqual('Test.Mock.Thing'); - expect(key).toEqual('key'); + expect(bucket).toEqual('Test.Mock.Thing'); + expect(key).toEqual('key'); - return res(ctx.text('{ invalid: json string }')); - }), + return res(ctx.text('{ invalid: json string }')); + }, + ), ); await new Promise(resolve => { @@ -297,7 +315,7 @@ describe('Persistent Storage API', () => { server.use( rest.get( - `${mockBaseUrl}/buckets/:bucket/:key`, + `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (_req, res, ctx) => { return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) }))); }, diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts index 38a986863e..b23ecd2b3f 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts @@ -182,7 +182,7 @@ export class PersistentStorage implements StorageApi { const baseUrl = await this.discoveryApi.getBaseUrl('user-settings'); const encodedNamespace = encodeURIComponent(this.namespace); const encodedKey = encodeURIComponent(key); - return `${baseUrl}/buckets/${encodedNamespace}/${encodedKey}`; + return `${baseUrl}/buckets/${encodedNamespace}/keys/${encodedKey}`; } private async notifyChanges(snapshot: StorageValueSnapshot) { diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index 21aff9f164..a0e5403612 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -195,7 +195,7 @@ describe('createRouter', () => { }); }); - describe('GET /buckets/:bucket/:key', () => { + describe('GET /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; authenticateMock.mockResolvedValue({ @@ -205,7 +205,7 @@ describe('createRouter', () => { userSettingsStore.get.mockResolvedValue(setting); const responses = await request(app) - .get('/buckets/my-bucket/my-key') + .get('/buckets/my-bucket/keys/my-key') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(200); @@ -221,14 +221,16 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/my-bucket/my-key'); + const responses = await request(app).get( + '/buckets/my-bucket/keys/my-key', + ); expect(responses.status).toEqual(401); expect(userSettingsStore.get).not.toHaveBeenCalled(); }); }); - describe('DELETE /buckets/:bucket/:key', () => { + describe('DELETE /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { authenticateMock.mockResolvedValue({ identity: { userEntityRef: 'user-1' }, @@ -237,7 +239,7 @@ describe('createRouter', () => { userSettingsStore.delete.mockResolvedValue(); const responses = await request(app) - .delete('/buckets/my-bucket/my-key') + .delete('/buckets/my-bucket/keys/my-key') .set('Authorization', 'Bearer foo'); expect(responses.status).toEqual(204); @@ -252,14 +254,16 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/buckets/my-bucket/my-key'); + const responses = await request(app).delete( + '/buckets/my-bucket/keys/my-key', + ); expect(responses.status).toEqual(401); expect(userSettingsStore.delete).not.toHaveBeenCalled(); }); }); - describe('PUT /buckets/:bucket/:key', () => { + describe('PUT /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; authenticateMock.mockResolvedValue({ @@ -270,7 +274,7 @@ describe('createRouter', () => { userSettingsStore.get.mockResolvedValue(setting); const responses = await request(app) - .put('/buckets/my-bucket/my-key') + .put('/buckets/my-bucket/keys/my-key') .set('Authorization', 'Bearer foo') .send({ value: 'a' }); @@ -299,7 +303,7 @@ describe('createRouter', () => { }); const responses = await request(app) - .put('/buckets/my-bucket/my-key') + .put('/buckets/my-bucket/keys/my-key') .set('Authorization', 'Bearer foo') .send({ value: { invalid: 'because not a string' } }); @@ -310,7 +314,9 @@ describe('createRouter', () => { }); it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/my-bucket/my-key'); + const responses = await request(app).get( + '/buckets/my-bucket/keys/my-key', + ); expect(responses.status).toEqual(401); expect(userSettingsStore.get).not.toHaveBeenCalled(); diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index 588759c929..f51e38c10a 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -109,7 +109,7 @@ export async function createRouter( }); // get a single value - router.get('/buckets/:bucket/:key', async (req, res) => { + router.get('/buckets/:bucket/keys/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; @@ -121,7 +121,7 @@ export async function createRouter( }); // set a single value - router.put('/buckets/:bucket/:key', async (req, res) => { + router.put('/buckets/:bucket/keys/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; const { value } = req.body; @@ -144,7 +144,7 @@ export async function createRouter( }); // get a single value - router.delete('/buckets/:bucket/:key', async (req, res) => { + router.delete('/buckets/:bucket/keys/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; From 9895e6bfb2707eaee73c198d36db9268ed1afa6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 6 Sep 2022 10:50:49 +0200 Subject: [PATCH 48/95] rename to UserSettingsStorage and adjust error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/healthy-oranges-fly.md | 7 +- packages/core-app-api/api-report.md | 52 ++++++------- ...ge.test.ts => UserSettingsStorage.test.ts} | 20 +++-- ...stentStorage.ts => UserSettingsStorage.ts} | 78 +++++++++++-------- .../apis/implementations/StorageApi/index.ts | 2 +- .../DatabaseUserSettingsStore.test.ts | 2 +- .../src/database/DatabaseUserSettingsStore.ts | 2 +- .../src/database/index.ts | 1 + plugins/user-settings-backend/src/index.ts | 1 + plugins/user-settings-backend/src/run.ts | 1 + .../src/service/index.ts | 1 + .../src/service/router.test.ts | 2 +- .../src/service/router.ts | 2 +- .../src/service/standaloneServer.ts | 11 ++- .../user-settings-backend/src/setupTests.ts | 1 + 15 files changed, 97 insertions(+), 86 deletions(-) rename packages/core-app-api/src/apis/implementations/StorageApi/{PersistentStorage.test.ts => UserSettingsStorage.test.ts} (96%) rename packages/core-app-api/src/apis/implementations/StorageApi/{PersistentStorage.ts => UserSettingsStorage.ts} (73%) diff --git a/.changeset/healthy-oranges-fly.md b/.changeset/healthy-oranges-fly.md index da6530b903..c6b6f6ff93 100644 --- a/.changeset/healthy-oranges-fly.md +++ b/.changeset/healthy-oranges-fly.md @@ -3,6 +3,7 @@ '@backstage/plugin-user-settings-backend': minor --- -Add new plugin @backstage/user-settings-backend to store user related settings -in the database. Additionally adding a PersistentStorage implementation to use -easily use the new plugin as drop-in replacement for the WebStorage. +Add new plugin `@backstage/user-settings-backend` to store user related settings +in the database. Additionally adding a `UserSettingsStorage` implementation of +the `StorageApi` to easily use the new plugin as drop-in replacement for the +`WebStorage`. diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index de3afdcbd4..90e18df723 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -506,35 +506,6 @@ export type OneLoginAuthCreateOptions = { provider?: AuthProviderInfo; }; -// @public -export class PersistentStorage implements StorageApi { - constructor( - namespace: string, - fetchApi: FetchApi, - discoveryApi: DiscoveryApi, - errorApi: ErrorApi, - ); - // (undocumented) - static create(options: { - fetchApi: FetchApi; - discoveryApi: DiscoveryApi; - errorApi: ErrorApi; - namespace?: string; - }): PersistentStorage; - // (undocumented) - forBucket(name: string): StorageApi; - // (undocumented) - observe$( - key: string, - ): Observable>; - // (undocumented) - remove(key: string): Promise; - // (undocumented) - set(key: string, data: T): Promise; - // (undocumented) - snapshot(key: string): StorageValueSnapshot; -} - // @public export class SamlAuth implements ProfileInfoApi, BackstageIdentityApi, SessionApi @@ -572,6 +543,29 @@ export class UrlPatternDiscovery implements DiscoveryApi { getBaseUrl(pluginId: string): Promise; } +// @public +export class UserSettingsStorage implements StorageApi { + // (undocumented) + static create(options: { + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + errorApi: ErrorApi; + namespace?: string; + }): UserSettingsStorage; + // (undocumented) + forBucket(name: string): StorageApi; + // (undocumented) + observe$( + key: string, + ): Observable>; + // (undocumented) + remove(key: string): Promise; + // (undocumented) + set(key: string, data: T): Promise; + // (undocumented) + snapshot(key: string): StorageValueSnapshot; +} + // @public export class WebStorage implements StorageApi { constructor(namespace: string, errorApi: ErrorApi); diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts similarity index 96% rename from packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts rename to packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts index 79da01ca41..cc48fc925c 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts @@ -14,22 +14,21 @@ * limitations under the License. */ -import { PersistentStorage } from './PersistentStorage'; import { + DiscoveryApi, ErrorApi, FetchApi, StorageApi, - DiscoveryApi, } from '@backstage/core-plugin-api'; import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; - import { rest } from 'msw'; import { setupServer } from 'msw/node'; - -const server = setupServer(); +import { UserSettingsStorage } from './UserSettingsStorage'; describe('Persistent Storage API', () => { + const server = setupServer(); setupRequestMockHandlers(server); + const mockBaseUrl = 'http://backstage:9191/api'; const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; const mockDiscoveryApi = { getBaseUrl: async () => mockBaseUrl }; @@ -42,7 +41,7 @@ describe('Persistent Storage API', () => { namespace?: string; }>, ): StorageApi => { - return PersistentStorage.create({ + return UserSettingsStorage.create({ errorApi: mockErrorApi, fetchApi: new MockFetchApi(), discoveryApi: mockDiscoveryApi, @@ -58,7 +57,9 @@ describe('Persistent Storage API', () => { ); }); - afterEach(() => jest.resetAllMocks()); + afterEach(() => { + jest.resetAllMocks(); + }); it('should return undefined for values which are unset', async () => { const storage = createPersistentStorage(); @@ -267,7 +268,7 @@ describe('Persistent Storage API', () => { expect(mockErrorApi.post).not.toHaveBeenCalled(); }); - it('should call the error api when the json can not be parsed in local storage', async () => { + it('should silently treat the value as absent when the json can not be parsed', async () => { const selectedKeyNextHandler = jest.fn(); const rootStorage = createPersistentStorage({ namespace: 'Test.Mock.Thing', @@ -278,10 +279,8 @@ describe('Persistent Storage API', () => { `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (req, res, ctx) => { const { bucket, key } = req.params; - expect(bucket).toEqual('Test.Mock.Thing'); expect(key).toEqual('key'); - return res(ctx.text('{ invalid: json string }')); }, ), @@ -305,7 +304,6 @@ describe('Persistent Storage API', () => { presence: 'absent', value: undefined, }); - expect(mockErrorApi.post).toHaveBeenCalledWith(expect.any(Error)); }); it('should freeze the snapshot value', async () => { diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts similarity index 73% rename from packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts rename to packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts index b23ecd2b3f..0763ad8187 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/PersistentStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts @@ -21,11 +21,11 @@ import { StorageApi, StorageValueSnapshot, } from '@backstage/core-plugin-api'; -import { NotFoundError } from '@backstage/errors'; +import { ResponseError } from '@backstage/errors'; import { JsonValue, Observable } from '@backstage/types'; import ObservableImpl from 'zen-observable'; -const buckets = new Map(); +const buckets = new Map(); /** * An implementation of the storage API, that uses the user-settings backend to @@ -33,7 +33,7 @@ const buckets = new Map(); * * @public */ -export class PersistentStorage implements StorageApi { +export class UserSettingsStorage implements StorageApi { private subscribers = new Set< ZenObservable.SubscriptionObserver> >(); @@ -47,7 +47,7 @@ export class PersistentStorage implements StorageApi { }; }); - constructor( + private constructor( private readonly namespace: string, private readonly fetchApi: FetchApi, private readonly discoveryApi: DiscoveryApi, @@ -59,8 +59,8 @@ export class PersistentStorage implements StorageApi { discoveryApi: DiscoveryApi; errorApi: ErrorApi; namespace?: string; - }): PersistentStorage { - return new PersistentStorage( + }): UserSettingsStorage { + return new UserSettingsStorage( options.namespace ?? 'default', options.fetchApi, options.discoveryApi, @@ -75,7 +75,7 @@ export class PersistentStorage implements StorageApi { if (!buckets.has(bucketPath)) { buckets.set( bucketPath, - new PersistentStorage( + new UserSettingsStorage( bucketPath, this.fetchApi, this.discoveryApi, @@ -90,10 +90,14 @@ export class PersistentStorage implements StorageApi { async remove(key: string): Promise { const fetchUrl = await this.getFetchUrl(key); - await this.fetchApi.fetch(fetchUrl, { + const response = await this.fetchApi.fetch(fetchUrl, { method: 'DELETE', }); + if (!response.ok && response.status !== 404) { + throw ResponseError.fromResponse(response); + } + this.notifyChanges({ key, presence: 'absent', @@ -109,6 +113,10 @@ export class PersistentStorage implements StorageApi { body, }); + if (!response.ok) { + throw ResponseError.fromResponse(response); + } + const { value } = await response.json(); this.notifyChanges({ @@ -121,12 +129,16 @@ export class PersistentStorage implements StorageApi { observe$( key: string, ): Observable> { + // TODO(freben): Introduce server polling or similar, to ensure that different devices update when values change return this.observable.filter(({ key: messageKey }) => messageKey === key); } snapshot(key: string): StorageValueSnapshot { - // trigger a reload - this.get(key).then(snapshot => this.notifyChanges(snapshot)); + // trigger a reload, ensure it happens on the next tick (after returning) + Promise.resolve() + .then(() => this.get(key)) + .then(snapshot => this.notifyChanges(snapshot)) + .catch(error => this.errorApi.post(error)); return { key, @@ -137,20 +149,21 @@ export class PersistentStorage implements StorageApi { private async get( key: string, ): Promise> { + const fetchUrl = await this.getFetchUrl(key); + const response = await this.fetchApi.fetch(fetchUrl); + + if (response.status === 404) { + return { + key, + presence: 'absent', + }; + } + + if (!response.ok) { + throw ResponseError.fromResponse(response); + } + try { - const fetchUrl = await this.getFetchUrl(key); - const response = await this.fetchApi.fetch(fetchUrl); - - if (response.status === 404) { - throw new NotFoundError( - `Setting '${key}' is not set in bucket '${this.namespace}'`, - ); - } else if (!response.ok) { - throw new Error( - `Unable to fetch '${key}' from bucket '${this.namespace}'`, - ); - } - const { value: rawValue } = await response.json(); const value = JSON.parse(rawValue, (_key, val) => { if (typeof val === 'object' && val !== null) { @@ -164,16 +177,11 @@ export class PersistentStorage implements StorageApi { presence: 'present', value, }; - } catch (error) { - // NotFoundError shouldn't be recorded - if (error && !(error instanceof NotFoundError)) { - this.errorApi.post(error); - } - + } catch { + // If the value is not valid JSON, we return an unknown presence. This should never happen return { key, presence: 'absent', - value: undefined, }; } } @@ -185,9 +193,15 @@ export class PersistentStorage implements StorageApi { return `${baseUrl}/buckets/${encodedNamespace}/keys/${encodedKey}`; } - private async notifyChanges(snapshot: StorageValueSnapshot) { + private async notifyChanges( + snapshot: StorageValueSnapshot, + ) { for (const subscription of this.subscribers) { - subscription.next(snapshot); + try { + subscription.next(snapshot); + } catch { + // ignore + } } } } diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts index 70a8c9cbe1..e4162d120d 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts @@ -15,4 +15,4 @@ */ export { WebStorage } from './WebStorage'; -export { PersistentStorage } from './PersistentStorage'; +export { UserSettingsStorage } from './UserSettingsStorage'; diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts index 547beaa6b6..ed69bdcb59 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Knex } from 'knex'; - import { DatabaseUserSettingsStore, RawDbUserSettingsRow, diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts index 2e2eb6318a..961149c9ea 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { PluginDatabaseManager, resolvePackagePath, } from '@backstage/backend-common'; import { NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; - import { type UserSetting, UserSettingsStore } from './UserSettingsStore'; const migrationsDir = resolvePackagePath( diff --git a/plugins/user-settings-backend/src/database/index.ts b/plugins/user-settings-backend/src/database/index.ts index 23023ceb2d..2552b7db13 100644 --- a/plugins/user-settings-backend/src/database/index.ts +++ b/plugins/user-settings-backend/src/database/index.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { DatabaseUserSettingsStore, type RawDbUserSettingsRow, diff --git a/plugins/user-settings-backend/src/index.ts b/plugins/user-settings-backend/src/index.ts index 9d9fe923e4..04d8accdaf 100644 --- a/plugins/user-settings-backend/src/index.ts +++ b/plugins/user-settings-backend/src/index.ts @@ -13,5 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export * from './service'; export * from './database'; diff --git a/plugins/user-settings-backend/src/run.ts b/plugins/user-settings-backend/src/run.ts index a1ba29a339..178de0f786 100644 --- a/plugins/user-settings-backend/src/run.ts +++ b/plugins/user-settings-backend/src/run.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { getRootLogger } from '@backstage/backend-common'; import yn from 'yn'; diff --git a/plugins/user-settings-backend/src/service/index.ts b/plugins/user-settings-backend/src/service/index.ts index 8f3e084d24..8ec00d13c8 100644 --- a/plugins/user-settings-backend/src/service/index.ts +++ b/plugins/user-settings-backend/src/service/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export { createRouter, type RouterOptions } from './router'; diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index a0e5403612..c1feb284a0 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { AuthenticationError } from '@backstage/errors'; import { IdentityClient } from '@backstage/plugin-auth-node'; import express from 'express'; import request from 'supertest'; - import { UserSettingsStore } from '../database'; import { createRouter } from './router'; diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index f51e38c10a..58580eddda 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { errorHandler } from '@backstage/backend-common'; import { AuthenticationError, InputError } from '@backstage/errors'; import { @@ -21,7 +22,6 @@ import { } from '@backstage/plugin-auth-node'; import express, { Request } from 'express'; import Router from 'express-promise-router'; - import { UserSettingsStore } from '../database'; /** diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 1e079f02c0..3cd3704ca8 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Server } from 'http'; import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common'; -import Knex from 'knex'; -import { Logger } from 'winston'; - -import { DatabaseUserSettingsStore } from '../database'; -import { createRouter } from './router'; import { IdentityClient } from '@backstage/plugin-auth-node'; import { Router } from 'express'; +import { Server } from 'http'; +import Knex from 'knex'; +import { Logger } from 'winston'; +import { DatabaseUserSettingsStore } from '../database'; +import { createRouter } from './router'; export interface ServerOptions { port: number; diff --git a/plugins/user-settings-backend/src/setupTests.ts b/plugins/user-settings-backend/src/setupTests.ts index 8b9b6bd586..813cdeaae3 100644 --- a/plugins/user-settings-backend/src/setupTests.ts +++ b/plugins/user-settings-backend/src/setupTests.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + export {}; From 46cda8068d8ae75a6eb40827e851e9572ccc2477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 6 Sep 2022 17:11:01 +0200 Subject: [PATCH 49/95] simplify router and db interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/user-settings-backend/api-report.md | 160 +--------- .../DatabaseUserSettingsStore.test.ts | 281 +++--------------- .../src/database/DatabaseUserSettingsStore.ts | 107 +++---- .../src/database/UserSettingsStore.ts | 53 ++-- .../src/database/index.ts | 6 +- .../src/service/router.test.ts | 165 +--------- .../src/service/router.ts | 106 +++---- .../src/service/standaloneServer.ts | 6 +- 8 files changed, 155 insertions(+), 729 deletions(-) diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 47e59637d6..15e8b5eb5b 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -5,169 +5,17 @@ ```ts import express from 'express'; import { IdentityClient } from '@backstage/plugin-auth-node'; -import { Knex } from 'knex'; import { PluginDatabaseManager } from '@backstage/backend-common'; // @public -export function createRouter( - options: RouterOptions, -): Promise; - -// @public -export class DatabaseUserSettingsStore - implements UserSettingsStore -{ - // (undocumented) - static create(options: { - database: PluginDatabaseManager; - }): Promise; - // (undocumented) - delete( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - deleteAll( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - deleteBucket( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - get( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - getAll( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - }, - ): Promise[]>; - // (undocumented) - getBucket( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - set( - tx: Knex.Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - value: string; - }, - ): Promise; - // (undocumented) - transaction(fn: (tx: Knex.Transaction) => Promise): Promise; -} +export function createRouter(options: RouterOptions): Promise; // @public (undocumented) -export type RawDbUserSettingsRow = { - user_entity_ref: string; - bucket: string; - key: string; - value: string; -}; - -// @public (undocumented) -export interface RouterOptions { +export interface RouterOptions { + // (undocumented) + database: PluginDatabaseManager; // (undocumented) identity: IdentityClient; - // (undocumented) - userSettingsStore: UserSettingsStore; -} - -// @public (undocumented) -export type UserSetting = { - bucket: string; - key: string; - value: string; -}; - -// @public -export interface UserSettingsStore { - // (undocumented) - delete( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - deleteAll( - tx: Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - deleteBucket( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - get( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - }, - ): Promise; - // (undocumented) - getAll( - tx: Transaction, - opts: { - userEntityRef: string; - }, - ): Promise; - // (undocumented) - getBucket( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - }, - ): Promise; - // (undocumented) - set( - tx: Transaction, - opts: { - userEntityRef: string; - bucket: string; - key: string; - value: string; - }, - ): Promise; - // (undocumented) - transaction(fn: (tx: Transaction) => Promise): Promise; } // (No @packageDocumentation comment for this package) diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts index ed69bdcb59..e98ee0010e 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -67,189 +67,14 @@ describe.each(databases.eachSupportedId())( .orderBy('user_entity_ref') .select(); - describe('getAll', () => { - it('should return empty user settings', async () => { - expect( - await storage.transaction(tx => - storage.getAll(tx, { userEntityRef: 'user-1' }), - ), - ).toEqual([]); - }); - - it('should return all user settings', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-b', - value: 'value-b', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - expect( - await storage.transaction(tx => - storage.getAll(tx, { userEntityRef: 'user-1' }), - ), - ).toEqual([ - { bucket: 'bucket-a', key: 'key-a', value: 'value-a' }, - { bucket: 'bucket-a', key: 'key-b', value: 'value-b' }, - { bucket: 'bucket-c', key: 'key-c', value: 'value-c' }, - ]); - }); - }); - - describe('deleteAll', () => { - it('should delete all user settings', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - await storage.transaction(tx => - storage.deleteAll(tx, { userEntityRef: 'user-1' }), - ); - - expect(await query()).toEqual([ - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - }); - }); - - describe('getBucket', () => { - it('should return an empty bucket', async () => { - expect( - await storage.transaction(tx => - storage.getBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - }), - ), - ).toEqual([]); - }); - - it('should return the settings of the bucket', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - expect( - await storage.transaction(tx => - storage.getBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - }), - ), - ).toEqual([{ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }]); - }); - }); - - describe('deleteBucket', () => { - it('should delete a bucket', async () => { - await insert([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }, - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - - await storage.transaction(tx => - storage.deleteBucket(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - }), - ); - - expect(await query()).toEqual([ - { - user_entity_ref: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - { - user_entity_ref: 'user-2', - bucket: 'bucket-c', - key: 'key-c', - value: 'value-c', - }, - ]); - }); - }); - describe('get', () => { it('should throw an error', async () => { await expect(() => - storage.transaction(tx => - storage.get(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - }), - ), + storage.get({ + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), ).rejects.toThrow(`Unable to find 'key-c' in bucket 'bucket-c'`); }); @@ -269,30 +94,30 @@ describe.each(databases.eachSupportedId())( }, ]); - expect( - await storage.transaction(tx => - storage.get(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - }), - ), - ).toEqual({ bucket: 'bucket-a', key: 'key-a', value: 'value-a' }); + await expect( + storage.get({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }), + ).resolves.toEqual({ + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); }); }); describe('set', () => { it('should insert a new setting', async () => { - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); - expect(await query()).toEqual([ + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-1', bucket: 'bucket-a', @@ -303,25 +128,21 @@ describe.each(databases.eachSupportedId())( }); it('should overwrite an existing setting', async () => { - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-a', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-a', + }); - await storage.transaction(tx => - storage.set(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - value: 'value-b', - }), - ); + await storage.set({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + value: 'value-b', + }); - expect(await query()).toEqual([ + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-1', bucket: 'bucket-a', @@ -334,15 +155,13 @@ describe.each(databases.eachSupportedId())( describe('delete', () => { it('should not throw an error if the entry does not exist', async () => { - await expect(() => - storage.transaction(tx => - storage.delete(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-c', - key: 'key-c', - }), - ), - ).not.toThrow(); + await expect( + storage.delete({ + userEntityRef: 'user-1', + bucket: 'bucket-c', + key: 'key-c', + }), + ).resolves.toBeUndefined(); }); it('should return the setting', async () => { @@ -361,14 +180,12 @@ describe.each(databases.eachSupportedId())( }, ]); - await storage.transaction(tx => - storage.delete(tx, { - userEntityRef: 'user-1', - bucket: 'bucket-a', - key: 'key-a', - }), - ); - expect(await query()).toEqual([ + await storage.delete({ + userEntityRef: 'user-1', + bucket: 'bucket-a', + key: 'key-a', + }); + await expect(query()).resolves.toEqual([ { user_entity_ref: 'user-2', bucket: 'bucket-c', diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts index 961149c9ea..4b46b6383f 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -42,9 +42,7 @@ export type RawDbUserSettingsRow = { * * @public */ -export class DatabaseUserSettingsStore - implements UserSettingsStore -{ +export class DatabaseUserSettingsStore implements UserSettingsStore { static async create(options: { database: PluginDatabaseManager; }): Promise { @@ -62,93 +60,56 @@ export class DatabaseUserSettingsStore private constructor(private readonly db: Knex) {} - async getAll(tx: Knex.Transaction, opts: { userEntityRef: string }) { - const settings = await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef }) - .select('bucket', 'key', 'value'); - - return settings; - } - - async deleteAll( - tx: Knex.Transaction, - opts: { userEntityRef: string }, - ): Promise { - await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef }) - .delete(); - } - - async getBucket( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise { - const settings = await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) - .select(['bucket', 'key', 'value']); - - return settings; - } - - async deleteBucket( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise { - await tx('user_settings') - .where({ user_entity_ref: opts.userEntityRef, bucket: opts.bucket }) - .delete(); - } - - async get( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise { - const setting = await tx('user_settings') + async get(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise { + const rows = await this.db('user_settings') .where({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, }) .select(['bucket', 'key', 'value']); - if (!setting.length) { + if (!rows.length) { throw new NotFoundError( - `Unable to find '${opts.key}' in bucket '${opts.bucket}'`, + `Unable to find '${options.key}' in bucket '${options.bucket}'`, ); } - return setting[0]; + return rows[0]; } - async set( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string; value: string }, - ): Promise { - await tx('user_settings') + async set(options: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }): Promise { + await this.db('user_settings') .insert({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, - value: opts.value, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, + value: options.value, }) .onConflict(['user_entity_ref', 'bucket', 'key']) - .merge({ value: opts.value }); + .merge(['value']); } - async delete( - tx: Knex.Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise { - await tx('user_settings') + async delete(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise { + await this.db('user_settings') .where({ - user_entity_ref: opts.userEntityRef, - bucket: opts.bucket, - key: opts.key, + user_entity_ref: options.userEntityRef, + bucket: options.bucket, + key: options.key, }) .delete(); } - - async transaction(fn: (tx: Knex.Transaction) => Promise) { - return await this.db.transaction(fn); - } } diff --git a/plugins/user-settings-backend/src/database/UserSettingsStore.ts b/plugins/user-settings-backend/src/database/UserSettingsStore.ts index b86673270f..d14af091ef 100644 --- a/plugins/user-settings-backend/src/database/UserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/UserSettingsStore.ts @@ -15,7 +15,7 @@ */ /** - * @public + * A single setting in a bucket */ export type UserSetting = { bucket: string; @@ -25,41 +25,24 @@ export type UserSetting = { /** * Store definition for the user settings. - * - * @public */ -export interface UserSettingsStore { - transaction(fn: (tx: Transaction) => Promise): Promise; +export interface UserSettingsStore { + get(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise; - get( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise; + set(options: { + userEntityRef: string; + bucket: string; + key: string; + value: string; + }): Promise; - set( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string; value: string }, - ): Promise; - - delete( - tx: Transaction, - opts: { userEntityRef: string; bucket: string; key: string }, - ): Promise; - - getBucket( - tx: Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise; - - deleteBucket( - tx: Transaction, - opts: { userEntityRef: string; bucket: string }, - ): Promise; - - getAll( - tx: Transaction, - opts: { userEntityRef: string }, - ): Promise; - - deleteAll(tx: Transaction, opts: { userEntityRef: string }): Promise; + delete(options: { + userEntityRef: string; + bucket: string; + key: string; + }): Promise; } diff --git a/plugins/user-settings-backend/src/database/index.ts b/plugins/user-settings-backend/src/database/index.ts index 2552b7db13..813cdeaae3 100644 --- a/plugins/user-settings-backend/src/database/index.ts +++ b/plugins/user-settings-backend/src/database/index.ts @@ -14,8 +14,4 @@ * limitations under the License. */ -export { - DatabaseUserSettingsStore, - type RawDbUserSettingsRow, -} from './DatabaseUserSettingsStore'; -export type { UserSettingsStore, UserSetting } from './UserSettingsStore'; +export {}; diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index c1feb284a0..7640714477 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -14,20 +14,14 @@ * limitations under the License. */ -import { AuthenticationError } from '@backstage/errors'; import { IdentityClient } from '@backstage/plugin-auth-node'; import express from 'express'; import request from 'supertest'; -import { UserSettingsStore } from '../database'; -import { createRouter } from './router'; +import { UserSettingsStore } from '../database/UserSettingsStore'; +import { createRouterInternal } from './router'; describe('createRouter', () => { - const userSettingsStore: jest.Mocked> = { - transaction: jest.fn(), - deleteAll: jest.fn(), - getAll: jest.fn(), - getBucket: jest.fn(), - deleteBucket: jest.fn(), + const userSettingsStore: jest.Mocked = { get: jest.fn(), set: jest.fn(), delete: jest.fn(), @@ -40,9 +34,7 @@ describe('createRouter', () => { let app: express.Express; beforeEach(async () => { - userSettingsStore.transaction.mockImplementation(fn => fn('tx')); - - const router = await createRouter({ + const router = await createRouterInternal({ userSettingsStore, identity: identityClient as IdentityClient, }); @@ -54,147 +46,6 @@ describe('createRouter', () => { jest.resetAllMocks(); }); - describe('GET /buckets/', () => { - it('returns ok', async () => { - const settings = [ - { bucket: 'a', key: 'a', value: 'a' }, - { bucket: 'b', key: 'b', value: 'b' }, - ]; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.getAll.mockResolvedValue(settings); - - const responses = await request(app) - .get('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(200); - expect(responses.body).toEqual(settings); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getAll).toHaveBeenCalledTimes(1); - expect(userSettingsStore.getAll).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - - it('returns an error if the token is not valid', async () => { - authenticateMock.mockRejectedValue( - new AuthenticationError('Invalid token'), - ); - - const responses = await request(app) - .get('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - }); - - describe('DELETE /buckets/', () => { - it('returns ok', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.deleteAll.mockResolvedValue(); - - const responses = await request(app) - .delete('/buckets/') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(204); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteAll).toHaveBeenCalledTimes(1); - expect(userSettingsStore.deleteAll).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/buckets/'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getAll).not.toHaveBeenCalled(); - }); - }); - - describe('GET /buckets/:bucket', () => { - it('returns ok', async () => { - const settings = [ - { bucket: 'my-bucket', key: 'a', value: 'a' }, - { bucket: 'my-bucket', key: 'b', value: 'b' }, - ]; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.getBucket.mockResolvedValue(settings); - - const responses = await request(app) - .get('/buckets/my-bucket') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(200); - expect(responses.body).toEqual(settings); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.getBucket).toHaveBeenCalledTimes(1); - expect(userSettingsStore.getBucket).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - bucket: 'my-bucket', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).get('/buckets/my-bucket'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.getBucket).not.toHaveBeenCalled(); - }); - }); - - describe('DELETE /buckets/:bucket', () => { - it('returns ok', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, - }); - - userSettingsStore.deleteBucket.mockResolvedValue(); - - const responses = await request(app) - .delete('/buckets/my-bucket') - .set('Authorization', 'Bearer foo'); - - expect(responses.status).toEqual(204); - - expect(authenticateMock).toHaveBeenCalledWith('foo'); - expect(userSettingsStore.deleteBucket).toHaveBeenCalledTimes(1); - expect(userSettingsStore.deleteBucket).toHaveBeenCalledWith('tx', { - userEntityRef: 'user-1', - bucket: 'my-bucket', - }); - }); - - it('returns an error if the Authorization header is missing', async () => { - const responses = await request(app).delete('/buckets/my-bucket'); - - expect(responses.status).toEqual(401); - expect(userSettingsStore.deleteBucket).not.toHaveBeenCalled(); - }); - }); - describe('GET /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; @@ -213,7 +64,7 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.get).toHaveBeenCalledTimes(1); - expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -246,7 +97,7 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.delete).toHaveBeenCalledTimes(1); - expect(userSettingsStore.delete).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.delete).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', @@ -283,14 +134,14 @@ describe('createRouter', () => { expect(authenticateMock).toHaveBeenCalledWith('foo'); expect(userSettingsStore.set).toHaveBeenCalledTimes(1); - expect(userSettingsStore.set).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.set).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', value: 'a', }); expect(userSettingsStore.get).toHaveBeenCalledTimes(1); - expect(userSettingsStore.get).toHaveBeenCalledWith('tx', { + expect(userSettingsStore.get).toHaveBeenCalledWith({ userEntityRef: 'user-1', bucket: 'my-bucket', key: 'my-key', diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index 58580eddda..d677ee4bfb 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { errorHandler } from '@backstage/backend-common'; +import { errorHandler, PluginDatabaseManager } from '@backstage/backend-common'; import { AuthenticationError, InputError } from '@backstage/errors'; import { getBearerTokenFromAuthorizationHeader, @@ -22,13 +22,14 @@ import { } from '@backstage/plugin-auth-node'; import express, { Request } from 'express'; import Router from 'express-promise-router'; -import { UserSettingsStore } from '../database'; +import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; +import { UserSettingsStore } from '../database/UserSettingsStore'; /** * @public */ -export interface RouterOptions { - userSettingsStore: UserSettingsStore; +export interface RouterOptions { + database: PluginDatabaseManager; identity: IdentityClient; } @@ -37,10 +38,23 @@ export interface RouterOptions { * * @public */ -export async function createRouter( - options: RouterOptions, +export async function createRouter( + options: RouterOptions, ): Promise { - const { userSettingsStore, identity } = options; + const userSettingsStore = await DatabaseUserSettingsStore.create({ + database: options.database, + }); + + return await createRouterInternal({ + userSettingsStore, + identity: options.identity, + }); +} + +export async function createRouterInternal(options: { + identity: IdentityClient; + userSettingsStore: UserSettingsStore; +}): Promise { const router = Router(); router.use(express.json()); @@ -57,65 +71,21 @@ export async function createRouter( } // throws an AuthenticationError in case the token is invalid - const user = await identity.authenticate(token); + const user = await options.identity.authenticate(token); return user.identity.userEntityRef; }; - // get all user related settings - router.get('/buckets', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - - const settings = await userSettingsStore.transaction(tx => - userSettingsStore.getAll(tx, { userEntityRef }), - ); - - res.json(settings); - }); - - // remove all user related settings - router.delete('/buckets', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - - await userSettingsStore.transaction(tx => - userSettingsStore.deleteAll(tx, { userEntityRef }), - ); - - res.send(204).end(); - }); - - // get a single bucket - router.get('/buckets/:bucket', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - const { bucket } = req.params; - - const settings = await userSettingsStore.transaction(tx => - userSettingsStore.getBucket(tx, { userEntityRef, bucket }), - ); - - res.json(settings); - }); - - // delete a whole bucket - router.delete('/buckets/:bucket', async (req, res) => { - const userEntityRef = await getUserEntityRef(req); - const { bucket } = req.params; - - await userSettingsStore.transaction(tx => - userSettingsStore.deleteBucket(tx, { userEntityRef, bucket }), - ); - - res.status(204).end(); - }); - // get a single value router.get('/buckets/:bucket/keys/:key', async (req, res) => { const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; - const setting = await userSettingsStore.transaction(tx => - userSettingsStore.get(tx, { userEntityRef, bucket, key }), - ); + const setting = await options.userSettingsStore.get({ + userEntityRef, + bucket, + key, + }); res.json(setting); }); @@ -130,14 +100,16 @@ export async function createRouter( throw new InputError('Value must be a string'); } - const setting = await userSettingsStore.transaction(async tx => { - await userSettingsStore.set(tx, { - userEntityRef, - bucket, - key, - value, - }); - return userSettingsStore.get(tx, { userEntityRef, bucket, key }); + await options.userSettingsStore.set({ + userEntityRef, + bucket, + key, + value, + }); + const setting = await options.userSettingsStore.get({ + userEntityRef, + bucket, + key, }); res.json(setting); @@ -148,9 +120,7 @@ export async function createRouter( const userEntityRef = await getUserEntityRef(req); const { bucket, key } = req.params; - await userSettingsStore.transaction(tx => - userSettingsStore.delete(tx, { userEntityRef, bucket, key }), - ); + await options.userSettingsStore.delete({ userEntityRef, bucket, key }); res.send(204).end(); }); diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 3cd3704ca8..28af3a163f 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -20,8 +20,8 @@ import { Router } from 'express'; import { Server } from 'http'; import Knex from 'knex'; import { Logger } from 'winston'; -import { DatabaseUserSettingsStore } from '../database'; -import { createRouter } from './router'; +import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; +import { createRouterInternal } from './router'; export interface ServerOptions { port: number; @@ -50,7 +50,7 @@ export async function startStandaloneServer( }), } as IdentityClient; - const router = await createRouter({ + const router = await createRouterInternal({ userSettingsStore: await DatabaseUserSettingsStore.create({ database: { getClient: async () => database }, }), From 9018da59a91126cc07666bb4b77170f962d8425d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 7 Sep 2022 09:45:43 +0200 Subject: [PATCH 50/95] do not double encode the value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../StorageApi/UserSettingsStorage.test.ts | 17 +++++------------ .../StorageApi/UserSettingsStorage.ts | 6 +++--- plugins/user-settings-backend/package.json | 1 + .../database/DatabaseUserSettingsStore.test.ts | 14 +++++++------- .../src/database/DatabaseUserSettingsStore.ts | 13 +++++++++---- .../src/database/UserSettingsStore.ts | 6 ++++-- .../src/service/router.test.ts | 4 ++-- .../user-settings-backend/src/service/router.ts | 4 ++-- yarn.lock | 1 + 9 files changed, 34 insertions(+), 32 deletions(-) diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts index cc48fc925c..d8ea87b38d 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts @@ -49,14 +49,6 @@ describe('Persistent Storage API', () => { }); }; - beforeEach(() => { - server.use( - rest.get(`${mockBaseUrl}/buckets/`, async (_req, res, ctx) => { - return res(ctx.json([])); - }), - ); - }); - afterEach(() => { jest.resetAllMocks(); }); @@ -90,7 +82,8 @@ describe('Persistent Storage API', () => { `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (req, res, ctx) => { const body = await req.json(); - const data = { value: JSON.stringify(dummyValue) }; + const data = { value: dummyValue }; + expect(body).toEqual(data); return res(ctx.json(data)); @@ -113,7 +106,7 @@ describe('Persistent Storage API', () => { `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (req, res, ctx) => { const body = await req.json(); - const data = { value: JSON.stringify(dummyValue) }; + const data = { value: dummyValue }; expect(body).toEqual(data); return res(ctx.json(data)); @@ -136,7 +129,7 @@ describe('Persistent Storage API', () => { `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (req, res, ctx) => { const body = await req.json(); - const data = { value: JSON.stringify(mockData) }; + const data = { value: mockData }; expect(body).toEqual(data); return res(ctx.json(data)); @@ -315,7 +308,7 @@ describe('Persistent Storage API', () => { rest.get( `${mockBaseUrl}/buckets/:bucket/keys/:key`, async (_req, res, ctx) => { - return res(ctx.text(JSON.stringify({ value: JSON.stringify(data) }))); + return res(ctx.json({ value: data })); }, ), ); diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts index 0763ad8187..d01d5021ee 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts @@ -106,7 +106,7 @@ export class UserSettingsStorage implements StorageApi { async set(key: string, data: T): Promise { const fetchUrl = await this.getFetchUrl(key); - const body = JSON.stringify({ value: JSON.stringify(data) }); + const body = JSON.stringify({ value: data }); const response = await this.fetchApi.fetch(fetchUrl, { method: 'PUT', @@ -121,7 +121,7 @@ export class UserSettingsStorage implements StorageApi { this.notifyChanges({ key, - value: JSON.parse(value), + value, presence: 'present', }); } @@ -165,7 +165,7 @@ export class UserSettingsStorage implements StorageApi { try { const { value: rawValue } = await response.json(); - const value = JSON.parse(rawValue, (_key, val) => { + const value = JSON.parse(JSON.stringify(rawValue), (_key, val) => { if (typeof val === 'object' && val !== null) { Object.freeze(val); } diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 41178d49b8..690d1d13c9 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -32,6 +32,7 @@ "@backstage/catalog-model": "^1.1.0", "@backstage/errors": "^1.1.0", "@backstage/plugin-auth-node": "^0.2.5-next.1", + "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts index e98ee0010e..eb50e26179 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.test.ts @@ -84,13 +84,13 @@ describe.each(databases.eachSupportedId())( user_entity_ref: 'user-1', bucket: 'bucket-a', key: 'key-a', - value: 'value-a', + value: JSON.stringify('value-a'), }, { user_entity_ref: 'user-2', bucket: 'bucket-c', key: 'key-c', - value: 'value-c', + value: JSON.stringify('value-c'), }, ]); @@ -122,7 +122,7 @@ describe.each(databases.eachSupportedId())( user_entity_ref: 'user-1', bucket: 'bucket-a', key: 'key-a', - value: 'value-a', + value: JSON.stringify('value-a'), }, ]); }); @@ -147,7 +147,7 @@ describe.each(databases.eachSupportedId())( user_entity_ref: 'user-1', bucket: 'bucket-a', key: 'key-a', - value: 'value-b', + value: JSON.stringify('value-b'), }, ]); }); @@ -170,13 +170,13 @@ describe.each(databases.eachSupportedId())( user_entity_ref: 'user-1', bucket: 'bucket-a', key: 'key-a', - value: 'value-a', + value: JSON.stringify('value-a'), }, { user_entity_ref: 'user-2', bucket: 'bucket-c', key: 'key-c', - value: 'value-c', + value: JSON.stringify('value-c'), }, ]); @@ -190,7 +190,7 @@ describe.each(databases.eachSupportedId())( user_entity_ref: 'user-2', bucket: 'bucket-c', key: 'key-c', - value: 'value-c', + value: JSON.stringify('value-c'), }, ]); }); diff --git a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts index 4b46b6383f..b0fe8fdecc 100644 --- a/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/DatabaseUserSettingsStore.ts @@ -19,8 +19,9 @@ import { resolvePackagePath, } from '@backstage/backend-common'; import { NotFoundError } from '@backstage/errors'; +import { JsonValue } from '@backstage/types'; import { Knex } from 'knex'; -import { type UserSetting, UserSettingsStore } from './UserSettingsStore'; +import { UserSettingsStore, type UserSetting } from './UserSettingsStore'; const migrationsDir = resolvePackagePath( '@backstage/plugin-user-settings-backend', @@ -79,21 +80,25 @@ export class DatabaseUserSettingsStore implements UserSettingsStore { ); } - return rows[0]; + return { + bucket: rows[0].bucket, + key: rows[0].key, + value: JSON.parse(rows[0].value), + }; } async set(options: { userEntityRef: string; bucket: string; key: string; - value: string; + value: JsonValue; }): Promise { await this.db('user_settings') .insert({ user_entity_ref: options.userEntityRef, bucket: options.bucket, key: options.key, - value: options.value, + value: JSON.stringify(options.value), }) .onConflict(['user_entity_ref', 'bucket', 'key']) .merge(['value']); diff --git a/plugins/user-settings-backend/src/database/UserSettingsStore.ts b/plugins/user-settings-backend/src/database/UserSettingsStore.ts index d14af091ef..289c37523e 100644 --- a/plugins/user-settings-backend/src/database/UserSettingsStore.ts +++ b/plugins/user-settings-backend/src/database/UserSettingsStore.ts @@ -14,13 +14,15 @@ * limitations under the License. */ +import { JsonValue } from '@backstage/types'; + /** * A single setting in a bucket */ export type UserSetting = { bucket: string; key: string; - value: string; + value: JsonValue; }; /** @@ -37,7 +39,7 @@ export interface UserSettingsStore { userEntityRef: string; bucket: string; key: string; - value: string; + value: JsonValue; }): Promise; delete(options: { diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index 7640714477..c8df77a845 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -148,7 +148,7 @@ describe('createRouter', () => { }); }); - it('returns an error if the value is not a string', async () => { + it('returns an error if the value is not given', async () => { authenticateMock.mockResolvedValue({ identity: { userEntityRef: 'user-1' }, }); @@ -156,7 +156,7 @@ describe('createRouter', () => { const responses = await request(app) .put('/buckets/my-bucket/keys/my-key') .set('Authorization', 'Bearer foo') - .send({ value: { invalid: 'because not a string' } }); + .send({}); expect(responses.status).toEqual(400); diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index d677ee4bfb..487a6b4fee 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -96,8 +96,8 @@ export async function createRouterInternal(options: { const { bucket, key } = req.params; const { value } = req.body; - if (typeof value !== 'string') { - throw new InputError('Value must be a string'); + if (value === undefined) { + throw new InputError('Missing required field "value"'); } await options.userSettingsStore.set({ diff --git a/yarn.lock b/yarn.lock index 9df599d106..4d821c0e64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7321,6 +7321,7 @@ __metadata: "@backstage/cli": ^0.19.0-next.1 "@backstage/errors": ^1.1.0 "@backstage/plugin-auth-node": ^0.2.5-next.1 + "@backstage/types": ^1.0.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 express: ^4.17.1 From 0f88eab1b7bca8dc5bc2f3c546aa29da23890b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 7 Sep 2022 11:53:53 +0200 Subject: [PATCH 51/95] use the IdentityApi properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/user-settings-backend/README.md | 61 +++++++------------ plugins/user-settings-backend/api-report.md | 4 +- .../src/service/router.test.ts | 60 ++++++++++++------ .../src/service/router.ts | 22 +++---- .../src/service/standaloneServer.ts | 32 +++++----- 5 files changed, 89 insertions(+), 90 deletions(-) diff --git a/plugins/user-settings-backend/README.md b/plugins/user-settings-backend/README.md index 05a8c15c6d..5a98c86326 100644 --- a/plugins/user-settings-backend/README.md +++ b/plugins/user-settings-backend/README.md @@ -18,64 +18,47 @@ yarn --cwd packages/backend add @backstage/plugin-user-settings-backend ```ts // packages/backend/src/plugins/userSettings.ts -import { IdentityClient } from '@backstage/plugin-auth-node'; -import { - createRouter, - createUserSettingsStore, -} from '@backstage/plugin-user-settings-backend'; -import { Router } from 'express'; - +import { createRouter } from '@backstage/plugin-user-settings-backend'; import { PluginEnvironment } from '../types'; -export default async function createPlugin({ - database, - discovery, -}: PluginEnvironment): Promise { - const identity = IdentityClient.create({ - discovery, - issuer: await discovery.getExternalBaseUrl('auth'), - }); - +export default async function createPlugin(env: PluginEnvironment) { return await createRouter({ - userSettingsStore: await createUserSettingsStore(database), - identity, + database: env.database, + identity: env.identity, }); } ``` -3. Add the new routes to your backend by modifying the - `packages/backend/src/index.ts`: +3. Add the new routes to your backend by modifying `packages/backend/src/index.ts`: ```diff -// packages/backend/src/index.ts -+ import userSettings from './plugins/userSettings'; -async function main() { -+ const userSettingsEnv = useHotMemoize(module, () => -+ createEnv('userSettings'), -+ ); - const apiRouter = Router(); -+ apiRouter.use('/user-settings', await userSettings(userSettingsEnv)); + // packages/backend/src/index.ts ++import userSettings from './plugins/userSettings'; + async function main() { ++ const userSettingsEnv = useHotMemoize(module, () => createEnv('userSettings')); + const apiRouter = Router(); ++ apiRouter.use('/user-settings', await userSettings(userSettingsEnv)); } ``` ## Setup app To make use of the user settings backend, replace the `WebStorage` with the -`PersistentStorage` by using the `storageApiRef`. +`UserSettingsStorage` by using the `storageApiRef`. ```diff -// packages/app/src/apis.ts -import { - AnyApiFactory, - createApiFactory, + // packages/app/src/apis.ts + import { + AnyApiFactory, + createApiFactory, + discoveryApiRef, + fetchApiRef - errorApiRef, + errorApiRef, + storageApiRef, -} from '@backstage/core-plugin-api'; -+ import { PersistentStorage } from '@backstage/core-app-api'; + } from '@backstage/core-plugin-api'; ++import { UserSettingsStorage } from '@backstage/core-app-api'; -export const apis: AnyApiFactory[] = [ + export const apis: AnyApiFactory[] = [ + createApiFactory({ + api: storageApiRef, + deps: { @@ -84,9 +67,9 @@ export const apis: AnyApiFactory[] = [ + fetchApi: fetchApiRef, + }, + factory: ({ discoveryApi, errorApi, fetchApi }) => -+ PersistentStorage.create({ discoveryApi, errorApi, fetchApi }), ++ UserSettingsStorage.create({ discoveryApi, errorApi, fetchApi }), + }), -]; + ]; ``` ## Development diff --git a/plugins/user-settings-backend/api-report.md b/plugins/user-settings-backend/api-report.md index 15e8b5eb5b..1bc37bbec7 100644 --- a/plugins/user-settings-backend/api-report.md +++ b/plugins/user-settings-backend/api-report.md @@ -4,7 +4,7 @@ ```ts import express from 'express'; -import { IdentityClient } from '@backstage/plugin-auth-node'; +import { IdentityApi } from '@backstage/plugin-auth-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; // @public @@ -15,7 +15,7 @@ export interface RouterOptions { // (undocumented) database: PluginDatabaseManager; // (undocumented) - identity: IdentityClient; + identity: IdentityApi; } // (No @packageDocumentation comment for this package) diff --git a/plugins/user-settings-backend/src/service/router.test.ts b/plugins/user-settings-backend/src/service/router.test.ts index c8df77a845..64cdfcc465 100644 --- a/plugins/user-settings-backend/src/service/router.test.ts +++ b/plugins/user-settings-backend/src/service/router.test.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { IdentityClient } from '@backstage/plugin-auth-node'; +import { + BackstageIdentityResponse, + IdentityApi, +} from '@backstage/plugin-auth-node'; import express from 'express'; import request from 'supertest'; import { UserSettingsStore } from '../database/UserSettingsStore'; @@ -26,9 +29,12 @@ describe('createRouter', () => { set: jest.fn(), delete: jest.fn(), }; - const authenticateMock = jest.fn(); - const identityClient: jest.Mocked> = { - authenticate: authenticateMock, + const getIdentityMock = jest.fn< + Promise, + any + >(); + const identityApi: jest.Mocked> = { + getIdentity: getIdentityMock, }; let app: express.Express; @@ -36,7 +42,7 @@ describe('createRouter', () => { beforeEach(async () => { const router = await createRouterInternal({ userSettingsStore, - identity: identityClient as IdentityClient, + identity: identityApi as IdentityApi, }); app = express().use(router); @@ -49,8 +55,13 @@ describe('createRouter', () => { describe('GET /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, + getIdentityMock.mockResolvedValue({ + token: 'a', + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: 'user-1', + }, }); userSettingsStore.get.mockResolvedValue(setting); @@ -62,7 +73,7 @@ describe('createRouter', () => { expect(responses.status).toEqual(200); expect(responses.body).toEqual(setting); - expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(getIdentityMock).toHaveBeenCalledTimes(1); expect(userSettingsStore.get).toHaveBeenCalledTimes(1); expect(userSettingsStore.get).toHaveBeenCalledWith({ userEntityRef: 'user-1', @@ -83,8 +94,13 @@ describe('createRouter', () => { describe('DELETE /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, + getIdentityMock.mockResolvedValue({ + token: 'a', + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: 'user-1', + }, }); userSettingsStore.delete.mockResolvedValue(); @@ -95,7 +111,7 @@ describe('createRouter', () => { expect(responses.status).toEqual(204); - expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(getIdentityMock).toHaveBeenCalledTimes(1); expect(userSettingsStore.delete).toHaveBeenCalledTimes(1); expect(userSettingsStore.delete).toHaveBeenCalledWith({ userEntityRef: 'user-1', @@ -117,8 +133,13 @@ describe('createRouter', () => { describe('PUT /buckets/:bucket/keys/:key', () => { it('returns ok', async () => { const setting = { bucket: 'my-bucket', key: 'my-key', value: 'a' }; - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, + getIdentityMock.mockResolvedValue({ + token: 'a', + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: 'user-1', + }, }); userSettingsStore.set.mockResolvedValue(); @@ -132,7 +153,7 @@ describe('createRouter', () => { expect(responses.status).toEqual(200); expect(responses.body).toEqual(setting); - expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(getIdentityMock).toHaveBeenCalledTimes(1); expect(userSettingsStore.set).toHaveBeenCalledTimes(1); expect(userSettingsStore.set).toHaveBeenCalledWith({ userEntityRef: 'user-1', @@ -149,8 +170,13 @@ describe('createRouter', () => { }); it('returns an error if the value is not given', async () => { - authenticateMock.mockResolvedValue({ - identity: { userEntityRef: 'user-1' }, + getIdentityMock.mockResolvedValue({ + token: 'a', + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: 'user-1', + }, }); const responses = await request(app) @@ -160,7 +186,7 @@ describe('createRouter', () => { expect(responses.status).toEqual(400); - expect(authenticateMock).toHaveBeenCalledWith('foo'); + expect(getIdentityMock).toHaveBeenCalledTimes(1); expect(userSettingsStore.set).not.toHaveBeenCalled(); }); diff --git a/plugins/user-settings-backend/src/service/router.ts b/plugins/user-settings-backend/src/service/router.ts index 487a6b4fee..6792042585 100644 --- a/plugins/user-settings-backend/src/service/router.ts +++ b/plugins/user-settings-backend/src/service/router.ts @@ -16,10 +16,7 @@ import { errorHandler, PluginDatabaseManager } from '@backstage/backend-common'; import { AuthenticationError, InputError } from '@backstage/errors'; -import { - getBearerTokenFromAuthorizationHeader, - IdentityClient, -} from '@backstage/plugin-auth-node'; +import { IdentityApi } from '@backstage/plugin-auth-node'; import express, { Request } from 'express'; import Router from 'express-promise-router'; import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; @@ -30,7 +27,7 @@ import { UserSettingsStore } from '../database/UserSettingsStore'; */ export interface RouterOptions { database: PluginDatabaseManager; - identity: IdentityClient; + identity: IdentityApi; } /** @@ -52,7 +49,7 @@ export async function createRouter( } export async function createRouterInternal(options: { - identity: IdentityClient; + identity: IdentityApi; userSettingsStore: UserSettingsStore; }): Promise { const router = Router(); @@ -62,18 +59,13 @@ export async function createRouterInternal(options: { * Helper method to extract the userEntityRef from the request. */ const getUserEntityRef = async (req: Request): Promise => { - const token = getBearerTokenFromAuthorizationHeader( - req.header('authorization'), - ); - - if (!token) { + // throws an AuthenticationError in case the token exists but is invalid + const identity = await options.identity.getIdentity({ request: req }); + if (!identity) { throw new AuthenticationError(`Missing token in 'authorization' header`); } - // throws an AuthenticationError in case the token is invalid - const user = await options.identity.authenticate(token); - - return user.identity.userEntityRef; + return identity.identity.userEntityRef; }; // get a single value diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 28af3a163f..6dd8c7f72d 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -15,8 +15,7 @@ */ import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common'; -import { IdentityClient } from '@backstage/plugin-auth-node'; -import { Router } from 'express'; +import { IdentityApi } from '@backstage/plugin-auth-node'; import { Server } from 'http'; import Knex from 'knex'; import { Logger } from 'winston'; @@ -44,11 +43,19 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); - const identityMock = { - authenticate: async token => ({ - identity: { userEntityRef: token ?? 'user:default/john_doe' }, - }), - } as IdentityClient; + const identityMock: IdentityApi = { + async getIdentity({ request }) { + const token = request.headers.authorization?.split(' ')[1]; + return { + identity: { + type: 'user', + ownershipEntityRefs: [], + userEntityRef: token || 'user:default/john_doe', + }, + token: token || 'no-token', + }; + }, + }; const router = await createRouterInternal({ userSettingsStore: await DatabaseUserSettingsStore.create({ @@ -57,18 +64,9 @@ export async function startStandaloneServer( identity: identityMock, }); - // set a custom authorization header to simplify the development - const authWrapper = Router(); - authWrapper.use((req, _res, next) => { - req.headers.authorization = - req.headers.authorization ?? 'Bearer user:default/john_doe'; - next(); - }); - authWrapper.use(router); - let service = createServiceBuilder(module) .setPort(options.port) - .addRouter('/user-settings', authWrapper); + .addRouter('/user-settings', router); if (options.enableCors) { service = service.enableCors({ origin: 'http://localhost:3000' }); From 8a57ffc0fa9c1c57d21439d8c28d4abc98b2db54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 8 Sep 2022 09:20:22 +0200 Subject: [PATCH 52/95] Ensure that we return stable observer references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/sixty-apes-wait.md | 5 + packages/core-app-api/api-report.md | 5 +- .../StorageApi/UserSettingsStorage.test.ts | 9 +- .../StorageApi/UserSettingsStorage.ts | 118 +++++++++++------- .../implementations/StorageApi/WebStorage.ts | 4 +- .../shortcuts/src/api/LocalStoredShortcuts.ts | 12 +- plugins/user-settings-backend/README.md | 9 +- 7 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 .changeset/sixty-apes-wait.md diff --git a/.changeset/sixty-apes-wait.md b/.changeset/sixty-apes-wait.md new file mode 100644 index 0000000000..1273307519 --- /dev/null +++ b/.changeset/sixty-apes-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-shortcuts': patch +--- + +Ensure that a stable observable is used in the shortcuts API diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 90e18df723..39e5388d68 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -550,6 +550,7 @@ export class UserSettingsStorage implements StorageApi { fetchApi: FetchApi; discoveryApi: DiscoveryApi; errorApi: ErrorApi; + identityApi: IdentityApi; namespace?: string; }): UserSettingsStorage; // (undocumented) @@ -579,7 +580,9 @@ export class WebStorage implements StorageApi { // (undocumented) get(key: string): T | undefined; // (undocumented) - observe$(key: string): Observable>; + observe$( + key: string, + ): Observable>; // (undocumented) remove(key: string): Promise; // (undocumented) diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts index d8ea87b38d..0ebd96d19c 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts @@ -18,6 +18,7 @@ import { DiscoveryApi, ErrorApi, FetchApi, + IdentityApi, StorageApi, } from '@backstage/core-plugin-api'; import { MockFetchApi, setupRequestMockHandlers } from '@backstage/test-utils'; @@ -31,7 +32,12 @@ describe('Persistent Storage API', () => { const mockBaseUrl = 'http://backstage:9191/api'; const mockErrorApi = { post: jest.fn(), error$: jest.fn() }; - const mockDiscoveryApi = { getBaseUrl: async () => mockBaseUrl }; + const mockDiscoveryApi = { + getBaseUrl: async () => mockBaseUrl, + }; + const mockIdentityApi: Partial = { + getCredentials: async () => ({ token: 'a-token' }), + }; const createPersistentStorage = ( args?: Partial<{ @@ -45,6 +51,7 @@ describe('Persistent Storage API', () => { errorApi: mockErrorApi, fetchApi: new MockFetchApi(), discoveryApi: mockDiscoveryApi, + identityApi: mockIdentityApi as IdentityApi, ...args, }); }; diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts index d01d5021ee..b595c524cf 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts @@ -18,12 +18,19 @@ import { DiscoveryApi, ErrorApi, FetchApi, + IdentityApi, StorageApi, StorageValueSnapshot, } from '@backstage/core-plugin-api'; import { ResponseError } from '@backstage/errors'; import { JsonValue, Observable } from '@backstage/types'; import ObservableImpl from 'zen-observable'; +import { WebStorage } from './WebStorage'; + +const JSON_HEADERS = { + 'Content-Type': 'application/json; charset=utf-8', + Accept: 'application/json', +}; const buckets = new Map(); @@ -38,26 +45,25 @@ export class UserSettingsStorage implements StorageApi { ZenObservable.SubscriptionObserver> >(); - private readonly observable = new ObservableImpl< - StorageValueSnapshot - >(subscriber => { - this.subscribers.add(subscriber); - return () => { - this.subscribers.delete(subscriber); - }; - }); + private readonly observables = new Map< + string, + Observable> + >(); private constructor( private readonly namespace: string, private readonly fetchApi: FetchApi, private readonly discoveryApi: DiscoveryApi, private readonly errorApi: ErrorApi, + private readonly identityApi: IdentityApi, + private readonly fallback: WebStorage, ) {} static create(options: { fetchApi: FetchApi; discoveryApi: DiscoveryApi; errorApi: ErrorApi; + identityApi: IdentityApi; namespace?: string; }): UserSettingsStorage { return new UserSettingsStorage( @@ -65,6 +71,11 @@ export class UserSettingsStorage implements StorageApi { options.fetchApi, options.discoveryApi, options.errorApi, + options.identityApi, + WebStorage.create({ + namespace: options.namespace, + errorApi: options.errorApi, + }), ); } @@ -80,6 +91,8 @@ export class UserSettingsStorage implements StorageApi { this.fetchApi, this.discoveryApi, this.errorApi, + this.identityApi, + this.fallback, ), ); } @@ -95,72 +108,81 @@ export class UserSettingsStorage implements StorageApi { }); if (!response.ok && response.status !== 404) { - throw ResponseError.fromResponse(response); + throw await ResponseError.fromResponse(response); } - this.notifyChanges({ - key, - presence: 'absent', - }); + this.notifyChanges({ key, presence: 'absent' }); } async set(key: string, data: T): Promise { + if (!(await this.isSignedIn())) { + await this.fallback.set(key, data); + this.notifyChanges({ key, presence: 'present', value: data }); + } + const fetchUrl = await this.getFetchUrl(key); - const body = JSON.stringify({ value: data }); const response = await this.fetchApi.fetch(fetchUrl, { method: 'PUT', - body, + headers: JSON_HEADERS, + body: JSON.stringify({ value: data }), }); if (!response.ok) { - throw ResponseError.fromResponse(response); + throw await ResponseError.fromResponse(response); } const { value } = await response.json(); - this.notifyChanges({ - key, - value, - presence: 'present', - }); + this.notifyChanges({ key, value, presence: 'present' }); } observe$( key: string, ): Observable> { - // TODO(freben): Introduce server polling or similar, to ensure that different devices update when values change - return this.observable.filter(({ key: messageKey }) => messageKey === key); + if (!this.observables.has(key)) { + this.observables.set( + key, + new ObservableImpl>(subscriber => { + this.subscribers.add(subscriber); + + // TODO(freben): Introduce server polling or similar, to ensure that different devices update when values change + Promise.resolve() + .then(() => this.get(key)) + .then(snapshot => subscriber.next(snapshot)) + .catch(error => this.errorApi.post(error)); + + return () => { + this.subscribers.delete(subscriber); + }; + }).filter(({ key: messageKey }) => messageKey === key), + ); + } + + return this.observables.get(key) as Observable>; } snapshot(key: string): StorageValueSnapshot { - // trigger a reload, ensure it happens on the next tick (after returning) - Promise.resolve() - .then(() => this.get(key)) - .then(snapshot => this.notifyChanges(snapshot)) - .catch(error => this.errorApi.post(error)); - - return { - key, - presence: 'unknown', - }; + return { key, presence: 'unknown' }; } private async get( key: string, ): Promise> { + if (!(await this.isSignedIn())) { + // This explicitly uses WebStorage, which we know is synchronous and doesn't return presence: unknown + return this.fallback.snapshot(key); + } + const fetchUrl = await this.getFetchUrl(key); const response = await this.fetchApi.fetch(fetchUrl); if (response.status === 404) { - return { - key, - presence: 'absent', - }; + return { key, presence: 'absent' }; } if (!response.ok) { - throw ResponseError.fromResponse(response); + throw await ResponseError.fromResponse(response); } try { @@ -172,17 +194,10 @@ export class UserSettingsStorage implements StorageApi { return val; }); - return { - key, - presence: 'present', - value, - }; + return { key, presence: 'present', value }; } catch { // If the value is not valid JSON, we return an unknown presence. This should never happen - return { - key, - presence: 'absent', - }; + return { key, presence: 'absent' }; } } @@ -204,4 +219,13 @@ export class UserSettingsStorage implements StorageApi { } } } + + private async isSignedIn(): Promise { + try { + const credentials = await this.identityApi.getCredentials(); + return credentials?.token ? true : false; + } catch { + return false; + } + } } diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts index ac3d3f20f2..b0cbfbd883 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/WebStorage.ts @@ -86,7 +86,9 @@ export class WebStorage implements StorageApi { this.notifyChanges(key); } - observe$(key: string): Observable> { + observe$( + key: string, + ): Observable> { return this.observable.filter(({ key: messageKey }) => messageKey === key); } diff --git a/plugins/shortcuts/src/api/LocalStoredShortcuts.ts b/plugins/shortcuts/src/api/LocalStoredShortcuts.ts index 9f3561be67..65aeb86e3f 100644 --- a/plugins/shortcuts/src/api/LocalStoredShortcuts.ts +++ b/plugins/shortcuts/src/api/LocalStoredShortcuts.ts @@ -27,12 +27,16 @@ import Observable from 'zen-observable'; * @public */ export class LocalStoredShortcuts implements ShortcutApi { - constructor(private readonly storageApi: StorageApi) {} + private readonly shortcuts: Observable; + + constructor(private readonly storageApi: StorageApi) { + this.shortcuts = Observable.from( + this.storageApi.observe$('items'), + ).map(snapshot => snapshot.value ?? []); + } shortcut$() { - return Observable.from(this.storageApi.observe$('items')).map( - snapshot => snapshot.value ?? [], - ); + return this.shortcuts; } get() { diff --git a/plugins/user-settings-backend/README.md b/plugins/user-settings-backend/README.md index 5a98c86326..45e06731c9 100644 --- a/plugins/user-settings-backend/README.md +++ b/plugins/user-settings-backend/README.md @@ -35,7 +35,7 @@ export default async function createPlugin(env: PluginEnvironment) { // packages/backend/src/index.ts +import userSettings from './plugins/userSettings'; async function main() { -+ const userSettingsEnv = useHotMemoize(module, () => createEnv('userSettings')); ++ const userSettingsEnv = useHotMemoize(module, () => createEnv('user-settings')); const apiRouter = Router(); + apiRouter.use('/user-settings', await userSettings(userSettingsEnv)); } @@ -52,8 +52,9 @@ To make use of the user settings backend, replace the `WebStorage` with the AnyApiFactory, createApiFactory, + discoveryApiRef, -+ fetchApiRef ++ fetchApiRef, errorApiRef, ++ identityApi, + storageApiRef, } from '@backstage/core-plugin-api'; +import { UserSettingsStorage } from '@backstage/core-app-api'; @@ -65,9 +66,9 @@ To make use of the user settings backend, replace the `WebStorage` with the + discoveryApi: discoveryApiRef, + errorApi: errorApiRef, + fetchApi: fetchApiRef, ++ identityApi: identityApiRef + }, -+ factory: ({ discoveryApi, errorApi, fetchApi }) => -+ UserSettingsStorage.create({ discoveryApi, errorApi, fetchApi }), ++ factory: deps => UserSettingsStorage.create(deps), + }), ]; ``` From 294805ed598df10f2e1b090f8bbc1f2f4c0a6956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 19 Sep 2022 13:23:48 +0200 Subject: [PATCH 53/95] refresh internal version deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- packages/core-app-api/package.json | 2 +- plugins/user-settings-backend/package.json | 10 +++++----- yarn.lock | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index e1c24997ac..b6e2f64889 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -34,7 +34,7 @@ "dependencies": { "@backstage/config": "^1.0.2-next.0", "@backstage/core-plugin-api": "^1.0.6-next.3", - "@backstage/errors": "^1.1.0", + "@backstage/errors": "^1.1.1-next.0", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 690d1d13c9..f1b4b503e1 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -28,10 +28,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/backend-common": "^0.15.1-next.1", - "@backstage/catalog-model": "^1.1.0", - "@backstage/errors": "^1.1.0", - "@backstage/plugin-auth-node": "^0.2.5-next.1", + "@backstage/backend-common": "^0.15.1-next.3", + "@backstage/catalog-model": "^1.1.1-next.0", + "@backstage/errors": "^1.1.1-next.0", + "@backstage/plugin-auth-node": "^0.2.5-next.3", "@backstage/types": "^1.0.0", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -41,7 +41,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.28-next.1", + "@backstage/backend-test-utils": "^0.1.28-next.3", "@backstage/cli": "^0.19.0-next.1", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" diff --git a/yarn.lock b/yarn.lock index 4d821c0e64..a9f5a553b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2855,7 +2855,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-common@^0.15.1-next.1, @backstage/backend-common@^0.15.1-next.3, @backstage/backend-common@workspace:packages/backend-common": +"@backstage/backend-common@^0.15.1-next.3, @backstage/backend-common@workspace:packages/backend-common": version: 0.0.0-use.local resolution: "@backstage/backend-common@workspace:packages/backend-common" dependencies: @@ -2991,7 +2991,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/backend-test-utils@^0.1.28-next.1, @backstage/backend-test-utils@^0.1.28-next.3, @backstage/backend-test-utils@workspace:packages/backend-test-utils": +"@backstage/backend-test-utils@^0.1.28-next.3, @backstage/backend-test-utils@workspace:packages/backend-test-utils": version: 0.0.0-use.local resolution: "@backstage/backend-test-utils@workspace:packages/backend-test-utils" dependencies: @@ -3291,7 +3291,7 @@ __metadata: "@backstage/cli": ^0.19.0-next.3 "@backstage/config": ^1.0.2-next.0 "@backstage/core-plugin-api": ^1.0.6-next.3 - "@backstage/errors": ^1.1.0 + "@backstage/errors": ^1.1.1-next.0 "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 @@ -4028,7 +4028,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-auth-node@^0.2.5-next.1, @backstage/plugin-auth-node@^0.2.5-next.3, @backstage/plugin-auth-node@workspace:plugins/auth-node": +"@backstage/plugin-auth-node@^0.2.5-next.3, @backstage/plugin-auth-node@workspace:plugins/auth-node": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-node@workspace:plugins/auth-node" dependencies: @@ -7315,12 +7315,12 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-user-settings-backend@workspace:plugins/user-settings-backend" dependencies: - "@backstage/backend-common": ^0.15.1-next.1 - "@backstage/backend-test-utils": ^0.1.28-next.1 - "@backstage/catalog-model": ^1.1.0 + "@backstage/backend-common": ^0.15.1-next.3 + "@backstage/backend-test-utils": ^0.1.28-next.3 + "@backstage/catalog-model": ^1.1.1-next.0 "@backstage/cli": ^0.19.0-next.1 - "@backstage/errors": ^1.1.0 - "@backstage/plugin-auth-node": ^0.2.5-next.1 + "@backstage/errors": ^1.1.1-next.0 + "@backstage/plugin-auth-node": ^0.2.5-next.3 "@backstage/types": ^1.0.0 "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 From d37a0ea6b6bc041d8c6ff16972fa920af77094b0 Mon Sep 17 00:00:00 2001 From: Nishkarsh Raj Date: Mon, 19 Sep 2022 17:06:30 +0530 Subject: [PATCH 54/95] Fixing document for CI/CD Statistics Plugin - GitLab Module Signed-off-by: Nishkarsh Raj --- plugins/cicd-statistics-module-gitlab/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cicd-statistics-module-gitlab/README.md b/plugins/cicd-statistics-module-gitlab/README.md index 0b11f6950a..7e1ae2016c 100644 --- a/plugins/cicd-statistics-module-gitlab/README.md +++ b/plugins/cicd-statistics-module-gitlab/README.md @@ -13,7 +13,7 @@ This is an extension module to the `cicd-statistics` plugin, providing a `CicdSt import { gitlabAuthApiRef } from '@backstage/core-plugin-api'; import { cicdStatisticsApiRef } from '@backstage/plugin-cicd-statistics'; -import { CicdStatisticsApiGitlab } from '@backstage plugin-cicd-statistics-module-gitlab'; +import { CicdStatisticsApiGitlab } from '@backstage/plugin-cicd-statistics-module-gitlab'; export const apis: AnyApiFactory[] = [ createApiFactory({ From 0f9b0750028f0fa80d555803868954b77ee7052e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 12:00:45 +0000 Subject: [PATCH 55/95] fix(deps): update dependency @types/passport to v1.0.11 Signed-off-by: Renovate Bot --- yarn.lock | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index afe89bf424..76250936ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14777,7 +14777,7 @@ __metadata: languageName: node linkType: hard -"@types/passport@npm:*, @types/passport@npm:^1.0.3": +"@types/passport@npm:*": version: 1.0.10 resolution: "@types/passport@npm:1.0.10" dependencies: @@ -14786,6 +14786,15 @@ __metadata: languageName: node linkType: hard +"@types/passport@npm:^1.0.3": + version: 1.0.11 + resolution: "@types/passport@npm:1.0.11" + dependencies: + "@types/express": "*" + checksum: 7fea92aeb0d05bd872c17deadc1f1219dbdb23bae1b8f50e1c432ef755bce2b5f3fd60af76c38815f1fbaa047960d3638a4144221c4330457091be1f6e492168 + languageName: node + linkType: hard + "@types/pluralize@npm:^0.0.29": version: 0.0.29 resolution: "@types/pluralize@npm:0.0.29" From 91e2abbd462aef9977caa3051f19d3181f7b00a9 Mon Sep 17 00:00:00 2001 From: Mengnan Gong Date: Mon, 19 Sep 2022 20:09:07 +0800 Subject: [PATCH 56/95] Remove the duplicated scheduleFn initialization in GitHubEntityProvider Signed-off-by: Mengnan Gong --- .changeset/yellow-tips-exist.md | 5 +++++ .../src/providers/GitHubEntityProvider.ts | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .changeset/yellow-tips-exist.md diff --git a/.changeset/yellow-tips-exist.md b/.changeset/yellow-tips-exist.md new file mode 100644 index 0000000000..d7b02533e0 --- /dev/null +++ b/.changeset/yellow-tips-exist.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-github': patch +--- + +Remove the duplicated `scheduleFn` initialization in `GitHubEntityProvider`. diff --git a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts index cf9b2cdd0a..3909b5a3c2 100644 --- a/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GitHubEntityProvider.ts @@ -98,7 +98,6 @@ export class GitHubEntityProvider implements EntityProvider { this.scheduleFn = this.createScheduleFn(schedule); this.githubCredentialsProvider = SingleInstanceGithubCredentialsProvider.create(integration.config); - this.scheduleFn = this.createScheduleFn(schedule); } /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */ From 0c780278e0d18924359e44c5add20cc2fb8e9fbc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 19 Sep 2022 14:21:27 +0200 Subject: [PATCH 57/95] backend-common: fix for zip entries being skipped Signed-off-by: Patrik Oldsberg --- .changeset/twelve-items-jump.md | 5 +++ .../reading/tree/ZipArchiveResponse.test.ts | 44 +++++++++++++++++++ .../src/reading/tree/ZipArchiveResponse.ts | 4 +- 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .changeset/twelve-items-jump.md diff --git a/.changeset/twelve-items-jump.md b/.changeset/twelve-items-jump.md new file mode 100644 index 0000000000..50bc8a4391 --- /dev/null +++ b/.changeset/twelve-items-jump.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Fix for entries being skipped or incomplete when reading large zip archives. diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts b/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts index 427c237802..e45a25db66 100644 --- a/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts +++ b/packages/backend-common/src/reading/tree/ZipArchiveResponse.test.ts @@ -16,6 +16,8 @@ import fs from 'fs-extra'; import mockFs from 'mock-fs'; +import { Readable } from 'stream'; +import { create as createArchive } from 'archiver'; import { resolve as resolvePath } from 'path'; import { ZipArchiveResponse } from './ZipArchiveResponse'; @@ -161,6 +163,48 @@ describe('ZipArchiveResponse', () => { ).resolves.toBe(false); }); + it('should extract a large archive', async () => { + const fileCount = 10; + const fileSize = 1000 * 1000; + const filePath = await new Promise((resolve, reject) => { + const outFile = '/large-archive.zip'; + const archive = createArchive('zip'); + + archive.on('error', reject); + archive.on('end', () => resolve(outFile)); + archive.pipe(fs.createWriteStream(outFile)); + archive.on('warning', w => console.warn('WARN', w)); + + for (let i = 0; i < fileCount; i++) { + // Workaround for https://github.com/archiverjs/node-archiver/issues/542 + // TODO(Rugvip): Without this workaround the archive entries end up with an uncompressed size of 0. + // That in turn causes yauzl to hang on extraction, because the internal transform error is ignored. + const stream = new Readable(); + stream.push(Buffer.alloc(fileSize, i)); + stream.push(null); + archive.append(stream, { name: `file-${i}.data` }); + } + + archive.finalize(); + }); + + const stream = fs.createReadStream(filePath); + + const res = new ZipArchiveResponse(stream, '', '/tmp', 'etag'); + const dir = await res.dir({ + targetDir: '/out', + }); + + expect(dir).toBe('/out'); + const files = await fs.readdir(dir); + expect(files).toHaveLength(fileCount); + + for (const file of files) { + const stat = await fs.stat(resolvePath(dir, file)); + expect(stat.size).toBe(fileSize); + } + }); + it('should throw on invalid archive', async () => { const stream = fs.createReadStream('/test-archive-corrupted.zip'); diff --git a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts b/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts index 4100af3d57..5a1c5f9688 100644 --- a/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts +++ b/packages/backend-common/src/reading/tree/ZipArchiveResponse.ts @@ -124,9 +124,11 @@ export class ZipArchiveResponse implements ReadTreeResponse { } await callback(entry, readStream); + zipfile.readEntry(); }); + } else { + zipfile.readEntry(); } - zipfile.readEntry(); }); zipfile.once('end', () => resolve()); zipfile.on('error', e => reject(e)); From c8e837da5b9427cacb1db5a3b562f11466226699 Mon Sep 17 00:00:00 2001 From: David Zemon Date: Mon, 19 Sep 2022 08:00:18 -0500 Subject: [PATCH 58/95] feat: Use JsonValue for JWT claim values Signed-off-by: David Zemon --- plugins/auth-backend/api-report.md | 2 +- plugins/auth-backend/src/identity/types.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 2420a79a79..6e9de12cdb 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -706,7 +706,7 @@ export type TokenParams = { claims: { sub: string; ent?: string[]; - } & Record; + } & Record; }; // @public (undocumented) diff --git a/plugins/auth-backend/src/identity/types.ts b/plugins/auth-backend/src/identity/types.ts index 49d78b8472..e325f74c81 100644 --- a/plugins/auth-backend/src/identity/types.ts +++ b/plugins/auth-backend/src/identity/types.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { JsonValue } from '@backstage/types'; + /** Represents any form of serializable JWK */ export interface AnyJWK extends Record { use: 'sig'; @@ -33,14 +35,15 @@ export type TokenParams = { * the subject claim, `sub`. It is common to also list entity ownership relations in the * `ent` list. Additional claims may also be added at the developer's discretion except * for the following list, which will be overwritten by the TokenIssuer: `iss`, `aud`, - * `iat`, and `exp`. + * `iat`, and `exp`. The Backstage team also maintains the right add new claims in the future + * without listing the change as a "breaking change". */ claims: { /** The token subject, i.e. User ID */ sub: string; /** A list of entity references that the user claims ownership through */ ent?: string[]; - } & Record; + } & Record; }; /** From 0ecc9a678482929c4fb9037103518d2943e5458b Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Mon, 12 Sep 2022 15:59:44 -0400 Subject: [PATCH 59/95] fix(scaffolder): properly set isDryRun flag in dry-run mode Signed-off-by: Phil Kuang --- .changeset/spicy-lizards-pay.md | 5 ++ .../tasks/NunjucksWorkflowRunner.test.ts | 31 ++++++++++ .../tasks/NunjucksWorkflowRunner.ts | 61 ++++++++++++++----- 3 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 .changeset/spicy-lizards-pay.md diff --git a/.changeset/spicy-lizards-pay.md b/.changeset/spicy-lizards-pay.md new file mode 100644 index 0000000000..285875560c --- /dev/null +++ b/.changeset/spicy-lizards-pay.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Properly set `ctx.isDryRun` when running actions in dry run mode. Also always log action inputs for debugging purposes when running in dry run mode. diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 8745b7afdf..24a35078e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -56,9 +56,11 @@ describe('DefaultWorkflowRunner', () => { const createMockTaskWithSpec = ( spec: TaskSpec, secrets?: TaskSecrets, + isDryRun?: boolean, ): TaskContext => ({ spec, secrets, + isDryRun, complete: async () => {}, done: false, emitLog: async () => {}, @@ -85,6 +87,7 @@ describe('DefaultWorkflowRunner', () => { actionRegistry.register({ id: 'jest-validated-action', description: 'Mock action for testing', + supportsDryRun: true, handler: fakeActionHandler, schema: { input: { @@ -640,4 +643,32 @@ describe('DefaultWorkflowRunner', () => { }); }); }); + + describe('dry run', () => { + it('sets isDryRun flag correctly', async () => { + const task = createMockTaskWithSpec( + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + parameters: {}, + output: {}, + steps: [ + { + id: 'test', + name: 'name', + action: 'jest-validated-action', + input: { foo: 1 }, + }, + ], + }, + { + backstageToken: 'secret', + }, + true, + ); + + await runner.execute(task); + + expect(fakeActionHandler.mock.calls[0][0].isDryRun).toEqual(true); + }); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index 6e35f7c69b..009ea1357d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -236,25 +236,53 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { const action = this.options.actionRegistry.get(step.action); const { taskLogger, streamLogger } = createStepLogger({ task, step }); - if (task.isDryRun && !action.supportsDryRun) { - task.emitLog( - `Skipping because ${action.id} does not support dry-run`, - { - stepId: step.id, - status: 'skipped', - }, + if (task.isDryRun) { + const redactedSecrets = Object.fromEntries( + Object.entries(task.secrets ?? {}).map(secret => [ + secret[0], + '[REDACTED]', + ]), ); - const outputSchema = action.schema?.output; - if (outputSchema) { - context.steps[step.id] = { - output: generateExampleOutput(outputSchema) as { - [name in string]: JsonValue; + const debugInput = + (step.input && + this.render( + step.input, + { + ...context, + secrets: redactedSecrets, + }, + renderTemplate, + )) ?? + {}; + taskLogger.info( + `Running ${ + action.id + } in dry-run mode with inputs (secrets redacted): ${JSON.stringify( + debugInput, + undefined, + 2, + )}`, + ); + if (!action.supportsDryRun) { + task.emitLog( + `Skipping because ${action.id} does not support dry-run`, + { + stepId: step.id, + status: 'skipped', }, - }; - } else { - context.steps[step.id] = { output: {} }; + ); + const outputSchema = action.schema?.output; + if (outputSchema) { + context.steps[step.id] = { + output: generateExampleOutput(outputSchema) as { + [name in string]: JsonValue; + }, + }; + } else { + context.steps[step.id] = { output: {} }; + } + continue; } - continue; } // Secrets are only passed when templating the input to actions for security reasons @@ -301,6 +329,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { }, templateInfo: task.spec.templateInfo, user: task.spec.user, + isDryRun: task.isDryRun, }); // Remove all temporary directories that were created when executing the action From 8448b53dd6f5366ce27337e3a473b08b1d23b89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 19 Sep 2022 15:21:10 +0200 Subject: [PATCH 60/95] move the settings storage to the user settings frontend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/healthy-oranges-fly.md | 7 ++-- .changeset/six-apricots-add.md | 7 ++++ .changeset/strange-geckos-know.md | 5 +++ packages/core-app-api/api-report.md | 24 -------------- packages/core-app-api/package.json | 1 - .../apis/implementations/StorageApi/index.ts | 1 - plugins/user-settings-backend/README.md | 2 +- plugins/user-settings/README.md | 12 ++++--- plugins/user-settings/api-report.md | 32 +++++++++++++++++++ plugins/user-settings/package.json | 7 ++-- .../StorageApi/UserSettingsStorage.test.ts | 0 .../apis}/StorageApi/UserSettingsStorage.ts | 2 +- .../src/apis/StorageApi/index.ts | 17 ++++++++++ plugins/user-settings/src/apis/index.ts | 17 ++++++++++ plugins/user-settings/src/index.ts | 3 +- yarn.lock | 4 ++- 16 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 .changeset/six-apricots-add.md create mode 100644 .changeset/strange-geckos-know.md rename {packages/core-app-api/src/apis/implementations => plugins/user-settings/src/apis}/StorageApi/UserSettingsStorage.test.ts (100%) rename {packages/core-app-api/src/apis/implementations => plugins/user-settings/src/apis}/StorageApi/UserSettingsStorage.ts (99%) create mode 100644 plugins/user-settings/src/apis/StorageApi/index.ts create mode 100644 plugins/user-settings/src/apis/index.ts diff --git a/.changeset/healthy-oranges-fly.md b/.changeset/healthy-oranges-fly.md index c6b6f6ff93..a10c56f4d0 100644 --- a/.changeset/healthy-oranges-fly.md +++ b/.changeset/healthy-oranges-fly.md @@ -1,9 +1,6 @@ --- -'@backstage/core-app-api': minor '@backstage/plugin-user-settings-backend': minor --- -Add new plugin `@backstage/user-settings-backend` to store user related settings -in the database. Additionally adding a `UserSettingsStorage` implementation of -the `StorageApi` to easily use the new plugin as drop-in replacement for the -`WebStorage`. +Added new plugin `@backstage/plugin-user-settings-backend` to store user related +settings in the database. diff --git a/.changeset/six-apricots-add.md b/.changeset/six-apricots-add.md new file mode 100644 index 0000000000..95ec68b1d5 --- /dev/null +++ b/.changeset/six-apricots-add.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Added a `UserSettingsStorage` implementation of the `StorageApi` for use as +drop-in replacement for the `WebStorage`, in conjunction with the newly created +`@backstage/plugin-user-settings-backend`. diff --git a/.changeset/strange-geckos-know.md b/.changeset/strange-geckos-know.md new file mode 100644 index 0000000000..b14762d3e5 --- /dev/null +++ b/.changeset/strange-geckos-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': patch +--- + +Clarify that the `WebStorage` observable returns `JsonValue` items. diff --git a/packages/core-app-api/api-report.md b/packages/core-app-api/api-report.md index 39e5388d68..4d1db6fde1 100644 --- a/packages/core-app-api/api-report.md +++ b/packages/core-app-api/api-report.md @@ -543,30 +543,6 @@ export class UrlPatternDiscovery implements DiscoveryApi { getBaseUrl(pluginId: string): Promise; } -// @public -export class UserSettingsStorage implements StorageApi { - // (undocumented) - static create(options: { - fetchApi: FetchApi; - discoveryApi: DiscoveryApi; - errorApi: ErrorApi; - identityApi: IdentityApi; - namespace?: string; - }): UserSettingsStorage; - // (undocumented) - forBucket(name: string): StorageApi; - // (undocumented) - observe$( - key: string, - ): Observable>; - // (undocumented) - remove(key: string): Promise; - // (undocumented) - set(key: string, data: T): Promise; - // (undocumented) - snapshot(key: string): StorageValueSnapshot; -} - // @public export class WebStorage implements StorageApi { constructor(namespace: string, errorApi: ErrorApi); diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index b6e2f64889..8532997477 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -34,7 +34,6 @@ "dependencies": { "@backstage/config": "^1.0.2-next.0", "@backstage/core-plugin-api": "^1.0.6-next.3", - "@backstage/errors": "^1.1.1-next.0", "@backstage/types": "^1.0.0", "@backstage/version-bridge": "^1.0.1", "@types/prop-types": "^15.7.3", diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts index e4162d120d..2f941381fd 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/index.ts +++ b/packages/core-app-api/src/apis/implementations/StorageApi/index.ts @@ -15,4 +15,3 @@ */ export { WebStorage } from './WebStorage'; -export { UserSettingsStorage } from './UserSettingsStorage'; diff --git a/plugins/user-settings-backend/README.md b/plugins/user-settings-backend/README.md index 45e06731c9..d12ee0aa89 100644 --- a/plugins/user-settings-backend/README.md +++ b/plugins/user-settings-backend/README.md @@ -57,7 +57,7 @@ To make use of the user settings backend, replace the `WebStorage` with the + identityApi, + storageApiRef, } from '@backstage/core-plugin-api'; -+import { UserSettingsStorage } from '@backstage/core-app-api'; ++import { UserSettingsStorage } from '@backstage/plugin-user-settings'; export const apis: AnyApiFactory[] = [ + createApiFactory({ diff --git a/plugins/user-settings/README.md b/plugins/user-settings/README.md index 13cfe720c8..abe66120fe 100644 --- a/plugins/user-settings/README.md +++ b/plugins/user-settings/README.md @@ -2,15 +2,17 @@ Welcome to the user-settings plugin! -_This plugin was created through the Backstage CLI_ - ## About the plugin -This plugin provides two components, `` is intended to be used within the [``](https://backstage.io/storybook/?path=/story/sidebar--sample-sidebar) and displays the signed-in users profile picture and name. +This plugin provides two components, `` is intended to be used within the [``](https://backstage.io/storybook/?path=/story/sidebar--sample-sidebar) and displays the signed-in users profile picture and name. The second component is a settings page where the user can control different settings across the App. -The second component is a settings page where the user can control different settings across the App. +It also provides a `UserSettingsStorage` implementation of the `StorageApi`, to +be used in the frontend as a persistent alternative to the builtin `WebStorage`. +Please see [the backend +README](https://github.com/backstage/backstage/tree/master/plugins/user-settings-backend) +for installation instructions. -## Usage +## Components Usage Add the item to the Sidebar: diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index bc5c3a9c70..76eaed940e 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -8,11 +8,19 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { BackstageUserIdentity } from '@backstage/core-plugin-api'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { ErrorApi } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; +import { IdentityApi } from '@backstage/core-plugin-api'; +import { JsonValue } from '@backstage/types'; +import { Observable } from '@backstage/types'; import { ProfileInfo } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; +import { StorageApi } from '@backstage/core-plugin-api'; +import { StorageValueSnapshot } from '@backstage/core-plugin-api'; // @public (undocumented) export const DefaultProviderSettings: (props: { @@ -83,6 +91,30 @@ export const UserSettingsSignInAvatar: (props: { size?: number; }) => JSX.Element; +// @public +export class UserSettingsStorage implements StorageApi { + // (undocumented) + static create(options: { + fetchApi: FetchApi; + discoveryApi: DiscoveryApi; + errorApi: ErrorApi; + identityApi: IdentityApi; + namespace?: string; + }): UserSettingsStorage; + // (undocumented) + forBucket(name: string): StorageApi; + // (undocumented) + observe$( + key: string, + ): Observable>; + // (undocumented) + remove(key: string): Promise; + // (undocumented) + set(key: string, data: T): Promise; + // (undocumented) + snapshot(key: string): StorageValueSnapshot; +} + // @public export const UserSettingsTab: (props: UserSettingsTabProps) => JSX.Element; diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index f99c0d206e..b4afc6766b 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -32,14 +32,18 @@ "clean": "backstage-cli package clean" }, "dependencies": { + "@backstage/core-app-api": "^1.1.0-next.3", "@backstage/core-components": "^0.11.1-next.3", "@backstage/core-plugin-api": "^1.0.6-next.3", + "@backstage/errors": "^1.1.1-next.0", "@backstage/theme": "^0.2.16", + "@backstage/types": "^1.0.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@types/react": "^16.13.1 || ^17.0.0", - "react-use": "^17.2.4" + "react-use": "^17.2.4", + "zen-observable": "^0.8.15" }, "peerDependencies": { "react": "^16.13.1 || ^17.0.0", @@ -47,7 +51,6 @@ }, "devDependencies": { "@backstage/cli": "^0.19.0-next.3", - "@backstage/core-app-api": "^1.1.0-next.3", "@backstage/dev-utils": "^1.0.6-next.2", "@backstage/test-utils": "^1.2.0-next.3", "@testing-library/jest-dom": "^5.10.1", diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts b/plugins/user-settings/src/apis/StorageApi/UserSettingsStorage.test.ts similarity index 100% rename from packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.test.ts rename to plugins/user-settings/src/apis/StorageApi/UserSettingsStorage.test.ts diff --git a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts b/plugins/user-settings/src/apis/StorageApi/UserSettingsStorage.ts similarity index 99% rename from packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts rename to plugins/user-settings/src/apis/StorageApi/UserSettingsStorage.ts index b595c524cf..8905b4aeea 100644 --- a/packages/core-app-api/src/apis/implementations/StorageApi/UserSettingsStorage.ts +++ b/plugins/user-settings/src/apis/StorageApi/UserSettingsStorage.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { WebStorage } from '@backstage/core-app-api'; import { DiscoveryApi, ErrorApi, @@ -25,7 +26,6 @@ import { import { ResponseError } from '@backstage/errors'; import { JsonValue, Observable } from '@backstage/types'; import ObservableImpl from 'zen-observable'; -import { WebStorage } from './WebStorage'; const JSON_HEADERS = { 'Content-Type': 'application/json; charset=utf-8', diff --git a/plugins/user-settings/src/apis/StorageApi/index.ts b/plugins/user-settings/src/apis/StorageApi/index.ts new file mode 100644 index 0000000000..9127cdfef4 --- /dev/null +++ b/plugins/user-settings/src/apis/StorageApi/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { UserSettingsStorage } from './UserSettingsStorage'; diff --git a/plugins/user-settings/src/apis/index.ts b/plugins/user-settings/src/apis/index.ts new file mode 100644 index 0000000000..1598430773 --- /dev/null +++ b/plugins/user-settings/src/apis/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 * from './StorageApi'; diff --git a/plugins/user-settings/src/index.ts b/plugins/user-settings/src/index.ts index 0654b7fced..bc878ecbb3 100644 --- a/plugins/user-settings/src/index.ts +++ b/plugins/user-settings/src/index.ts @@ -15,11 +15,12 @@ */ /** - * A Backstage plugin that provides a settings page + * A Backstage plugin that provides various per-user settings functionality. * * @packageDocumentation */ +export * from './apis'; export { userSettingsPlugin, userSettingsPlugin as plugin, diff --git a/yarn.lock b/yarn.lock index a9f5a553b9..69e6cb4267 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3291,7 +3291,6 @@ __metadata: "@backstage/cli": ^0.19.0-next.3 "@backstage/config": ^1.0.2-next.0 "@backstage/core-plugin-api": ^1.0.6-next.3 - "@backstage/errors": ^1.1.1-next.0 "@backstage/test-utils": ^1.2.0-next.3 "@backstage/types": ^1.0.0 "@backstage/version-bridge": ^1.0.1 @@ -7342,8 +7341,10 @@ __metadata: "@backstage/core-components": ^0.11.1-next.3 "@backstage/core-plugin-api": ^1.0.6-next.3 "@backstage/dev-utils": ^1.0.6-next.2 + "@backstage/errors": ^1.1.1-next.0 "@backstage/test-utils": ^1.2.0-next.3 "@backstage/theme": ^0.2.16 + "@backstage/types": ^1.0.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 @@ -7355,6 +7356,7 @@ __metadata: cross-fetch: ^3.1.5 msw: ^0.47.0 react-use: ^17.2.4 + zen-observable: ^0.8.15 peerDependencies: react: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 From 471abf7585324ed7f97367ed2bac3faa621258a1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 13:42:56 +0000 Subject: [PATCH 61/95] fix(deps): update dependency @yarnpkg/parsers to v3.0.0-rc.20 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 76250936ef..11b75e3583 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15933,12 +15933,12 @@ __metadata: linkType: hard "@yarnpkg/parsers@npm:^3.0.0-rc.4": - version: 3.0.0-rc.18 - resolution: "@yarnpkg/parsers@npm:3.0.0-rc.18" + version: 3.0.0-rc.20 + resolution: "@yarnpkg/parsers@npm:3.0.0-rc.20" dependencies: js-yaml: ^3.10.0 tslib: ^2.4.0 - checksum: 73cc59cb2349ce78a376d6ad7953117360de9aff866f42329a3e957ebabbbd4cbd91bfe79e30aa3bf07f126af66b72c00a7fc733724ac93d7f46d420ba81beec + checksum: a0dfc2d4d824322ae779363870ad7705b42161ad5e90c992404bf5dc0454a046a6f04144303c9bb047239e480b882b4105272127f2ba080b865180276c46deda languageName: node linkType: hard From 8117b58ae1b702086f046cd20762582b6ab6df62 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:00:14 +0000 Subject: [PATCH 62/95] chore(deps): update dependency msw to v0.47.3 Signed-off-by: Renovate Bot --- yarn.lock | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index e0bbd5f107..ac596f0b61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11376,18 +11376,19 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.17.2": - version: 0.17.2 - resolution: "@mswjs/interceptors@npm:0.17.2" +"@mswjs/interceptors@npm:^0.17.5": + version: 0.17.5 + resolution: "@mswjs/interceptors@npm:0.17.5" dependencies: "@open-draft/until": ^1.0.3 + "@types/debug": ^4.1.7 "@xmldom/xmldom": ^0.7.5 debug: ^4.3.3 - headers-polyfill: ^3.0.4 + headers-polyfill: ^3.1.0 outvariant: ^1.2.1 strict-event-emitter: ^0.2.4 web-encoding: ^1.1.5 - checksum: aa40a0389b6d1dac67ac488cc989f73122e94c1e2c765c59b85223e4c659c516dc0f8cef38b15ff8915d4f29c49e73681580f9fd24b656b9dc7078e5690457da + checksum: 0293ccc56c1c85fb7334cd5902574f7df20c26be74d633c83fde64ffd7620f81e08253fe7985c6b5ad3b64c04ad53c3610e9b9c07621518aabd977343026bb2b languageName: node linkType: hard @@ -14034,7 +14035,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.0.0": +"@types/debug@npm:^4.0.0, @types/debug@npm:^4.1.7": version: 4.1.7 resolution: "@types/debug@npm:4.1.7" dependencies: @@ -25032,6 +25033,13 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^3.1.0": + version: 3.1.0 + resolution: "headers-polyfill@npm:3.1.0" + checksum: a95257065684653b7185efbb9a380c547ea832002991b5adf0d90cd222073da2701be9dc2849d1970ecf15e8c35b383984358566afe6e76ca8ff1dbd7cdce3af + languageName: node + linkType: hard + "helmet@npm:^6.0.0": version: 6.0.0 resolution: "helmet@npm:6.0.0" @@ -30766,11 +30774,11 @@ __metadata: linkType: hard "msw@npm:^0.47.0": - version: 0.47.0 - resolution: "msw@npm:0.47.0" + version: 0.47.3 + resolution: "msw@npm:0.47.3" dependencies: "@mswjs/cookies": ^0.2.2 - "@mswjs/interceptors": ^0.17.2 + "@mswjs/interceptors": ^0.17.5 "@open-draft/until": ^1.0.3 "@types/cookie": ^0.4.1 "@types/js-levenshtein": ^1.1.1 @@ -30778,7 +30786,7 @@ __metadata: chokidar: ^3.4.2 cookie: ^0.4.2 graphql: ^15.0.0 || ^16.0.0 - headers-polyfill: ^3.0.4 + headers-polyfill: ^3.1.0 inquirer: ^8.2.0 is-node-process: ^1.0.1 js-levenshtein: ^1.1.6 @@ -30796,7 +30804,7 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: d48cd73327da0e44700595ebaaf0b8ee5f1b6c56c081d65ceed52dd8f49b64ce7a6734c84f8ab1093594e0c87b2554b6c35f7f92894c93148540dbfac826c441 + checksum: 1be018c7b2eff982409967cccb5c604e45f65710ee9698bab57fbe794f8426d1a4d33e52b75ef395c6d226948c799241c7c2c7748ec4f5b741e7f25bcbafbd1e languageName: node linkType: hard From 71b7464a7c041ce4bf0491dfc49e9433089c048f Mon Sep 17 00:00:00 2001 From: NishkarshRaj Date: Mon, 19 Sep 2022 20:48:40 +0530 Subject: [PATCH 63/95] chore: adding changesets to the PR Signed-off-by: NishkarshRaj --- .changeset/chatty-mangos-look.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chatty-mangos-look.md diff --git a/.changeset/chatty-mangos-look.md b/.changeset/chatty-mangos-look.md new file mode 100644 index 0000000000..e692085f11 --- /dev/null +++ b/.changeset/chatty-mangos-look.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cicd-statistics-module-gitlab': patch +--- + +Fixing typo in the Readme file: `'@backstage plugin-cicd-statistics-module-gitlab';` -> `'@backstage/plugin-cicd-statistics-module-gitlab';` From 9853a167b459e80a398d753c7299637653c5e783 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 19 Sep 2022 17:26:43 +0200 Subject: [PATCH 64/95] Update docker.md Signed-off-by: Patrik Oldsberg --- docs/deployment/docker.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/deployment/docker.md b/docs/deployment/docker.md index 5455babc6f..d35e7dd593 100644 --- a/docs/deployment/docker.md +++ b/docs/deployment/docker.md @@ -16,8 +16,8 @@ are stateless, so for a production deployment you will want to set up and connect to an external PostgreSQL instance where the backend plugins can store their state, rather than using SQLite. -It is in this section assumed that an [app](https://backstage.io/docs/getting-started/create-an-app) -has already been created with`@backstage/create-app`, in which the frontend is +This section assumes that an [app](https://backstage.io/docs/getting-started/create-an-app) +has already been created with `@backstage/create-app`, in which the frontend is bundled and served from the backend. This is done using the `@backstage/plugin-app-backend` plugin, which also injects the frontend configuration into the app. This means that you only need to build and deploy a From 4d0c66c16fe10889ed2a8663bc20801189c83ae7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:49:03 +0000 Subject: [PATCH 65/95] fix(deps): update dependency core-js to v3.25.2 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ac596f0b61..4718a3e0e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19602,9 +19602,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.25.1 - resolution: "core-js@npm:3.25.1" - checksum: bfacb078e790913841e2d5008b9b6705ae56ed23f83c7f0ae08d330d874561012611089d53b71520105234ed0abba36f28d91b391514a16541a8c8d98c464239 + version: 3.25.2 + resolution: "core-js@npm:3.25.2" + checksum: e93c6c645d44d98973efb07750975552ad405f080f5a563a99972ff6b2c5c6ee25705f55accd363f5dccd51e9e5f56be25e2be6c14a7294da65763e0e5659c02 languageName: node linkType: hard From 03fcff9a99811257286a124c52eba2b246420ec6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 16:47:18 +0000 Subject: [PATCH 66/95] fix(deps): update dependency eslint to v8.23.1 Signed-off-by: Renovate Bot --- yarn.lock | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4718a3e0e1..8c539bdbd7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8118,9 +8118,9 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^1.3.1": - version: 1.3.1 - resolution: "@eslint/eslintrc@npm:1.3.1" +"@eslint/eslintrc@npm:^1.3.2": + version: 1.3.2 + resolution: "@eslint/eslintrc@npm:1.3.2" dependencies: ajv: ^6.12.4 debug: ^4.3.2 @@ -8131,7 +8131,7 @@ __metadata: js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 9844dcc58a44399649926d5a17a2d53d529b80d3e8c3e9d0964ae198bac77ee6bb1cf44940f30cd9c2e300f7568ec82500be42ace6cacefb08aebf9905fe208e + checksum: 2074dca47d7e1c5c6323ff353f690f4b25d3ab53fe7d27337e2592d37a894cf60ca0e85ca66b50ff2db0bc7e630cc1e9c7347d65bb185b61416565584c38999c languageName: node linkType: hard @@ -22305,10 +22305,10 @@ __metadata: linkType: hard "eslint@npm:^8.6.0": - version: 8.23.0 - resolution: "eslint@npm:8.23.0" + version: 8.23.1 + resolution: "eslint@npm:8.23.1" dependencies: - "@eslint/eslintrc": ^1.3.1 + "@eslint/eslintrc": ^1.3.2 "@humanwhocodes/config-array": ^0.10.4 "@humanwhocodes/gitignore-to-minimatch": ^1.0.2 "@humanwhocodes/module-importer": ^1.0.1 @@ -22327,7 +22327,6 @@ __metadata: fast-deep-equal: ^3.1.3 file-entry-cache: ^6.0.1 find-up: ^5.0.0 - functional-red-black-tree: ^1.0.1 glob-parent: ^6.0.1 globals: ^13.15.0 globby: ^11.1.0 @@ -22336,6 +22335,7 @@ __metadata: import-fresh: ^3.0.0 imurmurhash: ^0.1.4 is-glob: ^4.0.0 + js-sdsl: ^4.1.4 js-yaml: ^4.1.0 json-stable-stringify-without-jsonify: ^1.0.1 levn: ^0.4.1 @@ -22349,7 +22349,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: ff6075daa28d817a7ac4508f31bc108a04d9ab5056608c8651b5bf9cfea5d708ca16dea6cdab2c3c0ae99b0bf0e726af8504eaa8e17c8e12e242cb68237ead64 + checksum: a727e15492786a03b438bcf021db49f715680679846a7b8d79b98ad34576f2a570404ffe882d3c3e26f6359bff7277ef11fae5614bfe8629adb653f20d018c71 languageName: node linkType: hard @@ -27583,6 +27583,13 @@ __metadata: languageName: node linkType: hard +"js-sdsl@npm:^4.1.4": + version: 4.1.4 + resolution: "js-sdsl@npm:4.1.4" + checksum: 1977cea4ab18e0e03e28bdf0371d8b443fad65ca0988e0faa216406faf6bb943714fe8f7cc7a5bfe5f35ba3d94ddae399f4d10200f547f2c3320688b0670d726 + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" From 72e610f0e49122e3ee5fcce2ad8d5da5669d9d39 Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Mon, 19 Sep 2022 15:57:13 -0400 Subject: [PATCH 67/95] pr feedback Signed-off-by: Matthew Clarke --- plugins/kubernetes-common/api-report.md | 18 +++++++++++++++ plugins/kubernetes-common/src/types.ts | 13 +++++++++++ plugins/kubernetes/api-report.md | 18 +++++---------- .../src/api/KubernetesBackendClient.ts | 23 ++++++++----------- plugins/kubernetes/src/api/types.ts | 12 ++++------ 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index 9485bd0294..85015662c6 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -89,6 +89,16 @@ export interface CronJobsFetchResponse { type: 'cronjobs'; } +// @public (undocumented) +export interface CustomObjectsByEntityRequest { + // (undocumented) + auth: KubernetesRequestAuth; + // (undocumented) + customResources: CustomResourceMatcher[]; + // (undocumented) + entity: Entity; +} + // @public (undocumented) export interface CustomResourceFetchResponse { // (undocumented) @@ -243,4 +253,12 @@ export interface StatefulSetsFetchResponse { // (undocumented) type: 'statefulsets'; } + +// @public (undocumented) +export interface WorkloadsByEntityRequest { + // (undocumented) + auth: KubernetesRequestAuth; + // (undocumented) + entity: Entity; +} ``` diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index 07378ae688..149caadb15 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -46,6 +46,19 @@ export interface CustomResourceMatcher { plural: string; } +/** @public */ +export interface WorkloadsByEntityRequest { + auth: KubernetesRequestAuth; + entity: Entity; +} + +/** @public */ +export interface CustomObjectsByEntityRequest { + auth: KubernetesRequestAuth; + customResources: CustomResourceMatcher[]; + entity: Entity; +} + /** @public */ export interface KubernetesRequestBody { auth?: KubernetesRequestAuth; diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 98ca4e4725..b7ec80aee3 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -10,12 +10,11 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; import { ClusterObjects } from '@backstage/plugin-kubernetes-common'; -import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; +import { CustomObjectsByEntityRequest } from '@backstage/plugin-kubernetes-common'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; import type { JsonObject } from '@backstage/types'; -import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; @@ -33,6 +32,7 @@ import { V1Pod } from '@kubernetes/client-node'; import { V1ReplicaSet } from '@kubernetes/client-node'; import { V1Service } from '@kubernetes/client-node'; import { V1StatefulSet } from '@kubernetes/client-node'; +import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common'; // Warning: (ae-forgotten-export) The symbol "ClusterProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Cluster" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -248,9 +248,7 @@ export interface KubernetesApi { >; // (undocumented) getCustomObjectsByEntity( - auth: KubernetesRequestAuth, - customResources: CustomResourceMatcher[], - entity: Entity, + request: CustomObjectsByEntityRequest, ): Promise; // (undocumented) getObjectsByEntity( @@ -258,8 +256,7 @@ export interface KubernetesApi { ): Promise; // (undocumented) getWorkloadsByEntity( - auth: KubernetesRequestAuth, - entity: Entity, + request: WorkloadsByEntityRequest, ): Promise; } @@ -318,9 +315,7 @@ export class KubernetesBackendClient implements KubernetesApi { >; // (undocumented) getCustomObjectsByEntity( - auth: KubernetesRequestAuth, - customResources: CustomResourceMatcher[], - entity: Entity, + request: CustomObjectsByEntityRequest, ): Promise; // (undocumented) getObjectsByEntity( @@ -328,8 +323,7 @@ export class KubernetesBackendClient implements KubernetesApi { ): Promise; // (undocumented) getWorkloadsByEntity( - auth: KubernetesRequestAuth, - entity: Entity, + request: WorkloadsByEntityRequest, ): Promise; } diff --git a/plugins/kubernetes/src/api/KubernetesBackendClient.ts b/plugins/kubernetes/src/api/KubernetesBackendClient.ts index 04f4624b24..bffc966333 100644 --- a/plugins/kubernetes/src/api/KubernetesBackendClient.ts +++ b/plugins/kubernetes/src/api/KubernetesBackendClient.ts @@ -16,13 +16,13 @@ import { KubernetesApi } from './types'; import { - KubernetesRequestAuth, KubernetesRequestBody, ObjectsByEntityResponse, - CustomResourceMatcher, + WorkloadsByEntityRequest, + CustomObjectsByEntityRequest, } from '@backstage/plugin-kubernetes-common'; import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api'; -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { stringifyEntityRef } from '@backstage/catalog-model'; export class KubernetesBackendClient implements KubernetesApi { private readonly discoveryApi: DiscoveryApi; @@ -79,24 +79,21 @@ export class KubernetesBackendClient implements KubernetesApi { } async getWorkloadsByEntity( - auth: KubernetesRequestAuth, - entity: Entity, + request: WorkloadsByEntityRequest, ): Promise { return await this.postRequired('/resources/workloads/query', { - auth, - entityRef: stringifyEntityRef(entity), + auth: request.auth, + entityRef: stringifyEntityRef(request.entity), }); } async getCustomObjectsByEntity( - auth: KubernetesRequestAuth, - customResources: CustomResourceMatcher[], - entity: Entity, + request: CustomObjectsByEntityRequest, ): Promise { return await this.postRequired(`/resources/custom/query`, { - entityRef: stringifyEntityRef(entity), - auth, - customResources, + entityRef: stringifyEntityRef(request.entity), + auth: request.auth, + customResources: request.customResources, }); } diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes/src/api/types.ts index b7e3f9fd49..0005a8d069 100644 --- a/plugins/kubernetes/src/api/types.ts +++ b/plugins/kubernetes/src/api/types.ts @@ -15,13 +15,12 @@ */ import { - KubernetesRequestAuth, KubernetesRequestBody, ObjectsByEntityResponse, - CustomResourceMatcher, + WorkloadsByEntityRequest, + CustomObjectsByEntityRequest, } from '@backstage/plugin-kubernetes-common'; import { createApiRef } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; export const kubernetesApiRef = createApiRef({ id: 'plugin.kubernetes.service', @@ -39,12 +38,9 @@ export interface KubernetesApi { }[] >; getWorkloadsByEntity( - auth: KubernetesRequestAuth, - entity: Entity, + request: WorkloadsByEntityRequest, ): Promise; getCustomObjectsByEntity( - auth: KubernetesRequestAuth, - customResources: CustomResourceMatcher[], - entity: Entity, + request: CustomObjectsByEntityRequest, ): Promise; } From 7a89391d176828e295998b03c1751fe89562b21b Mon Sep 17 00:00:00 2001 From: Matthew Clarke Date: Mon, 19 Sep 2022 16:07:23 -0400 Subject: [PATCH 68/95] fix dev Signed-off-by: Matthew Clarke --- plugins/kubernetes/dev/index.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx index 3dd0557ae1..05fcdefc8a 100644 --- a/plugins/kubernetes/dev/index.tsx +++ b/plugins/kubernetes/dev/index.tsx @@ -24,10 +24,10 @@ import { KubernetesApi, } from '../src'; import { - CustomResourceMatcher, + CustomObjectsByEntityRequest, FetchResponse, - KubernetesRequestAuth, ObjectsByEntityResponse, + WorkloadsByEntityRequest, } from '@backstage/plugin-kubernetes-common'; import fixture1 from '../src/__fixtures__/1-deployments.json'; import fixture2 from '../src/__fixtures__/2-deployments.json'; @@ -62,15 +62,12 @@ class MockKubernetesClient implements KubernetesApi { ); } async getWorkloadsByEntity( - _auth: KubernetesRequestAuth, - _entity: Entity, + _request: WorkloadsByEntityRequest, ): Promise { throw new Error('Method not implemented.'); } async getCustomObjectsByEntity( - _auth: KubernetesRequestAuth, - _customResources: CustomResourceMatcher[], - _entity: Entity, + _request: CustomObjectsByEntityRequest, ): Promise { throw new Error('Method not implemented.'); } From a246d5a9b8f284be374907f3d2c0e872284611ab Mon Sep 17 00:00:00 2001 From: Niels Henrik Hagen Date: Mon, 19 Sep 2022 22:13:20 +0200 Subject: [PATCH 69/95] Read queryMode from the microsoftGraphOrg config Closes: backstage/backstage#13638 Signed-off-by: Niels Henrik Hagen --- .changeset/lemon-chefs-grab.md | 5 +++++ .../catalog-backend-module-msgraph/config.d.ts | 18 ++++++++++++++++++ .../src/microsoftGraph/config.test.ts | 2 ++ .../src/microsoftGraph/config.ts | 10 ++++++++++ 4 files changed, 35 insertions(+) create mode 100644 .changeset/lemon-chefs-grab.md diff --git a/.changeset/lemon-chefs-grab.md b/.changeset/lemon-chefs-grab.md new file mode 100644 index 0000000000..6c020b7863 --- /dev/null +++ b/.changeset/lemon-chefs-grab.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Read `queryMode` from the `microsoftGraphOrg` config diff --git a/plugins/catalog-backend-module-msgraph/config.d.ts b/plugins/catalog-backend-module-msgraph/config.d.ts index df41b581f9..9fe1cb81c9 100644 --- a/plugins/catalog-backend-module-msgraph/config.d.ts +++ b/plugins/catalog-backend-module-msgraph/config.d.ts @@ -144,6 +144,15 @@ export interface Config { */ clientSecret?: string; + /** + * By default, the Microsoft Graph API only provides the basic feature set + * for querying. Certain features are limited to advanced query capabilities + * (see https://docs.microsoft.com/en-us/graph/aad-advanced-queries) + * and need to be enabled. + * + * Some features like `$expand` are not available for advanced queries, though. + */ + queryMode?: string; user?: { /** * The "expand" argument to apply to users. @@ -230,6 +239,15 @@ export interface Config { */ clientSecret: string; + /** + * By default, the Microsoft Graph API only provides the basic feature set + * for querying. Certain features are limited to advanced query capabilities + * (see https://docs.microsoft.com/en-us/graph/aad-advanced-queries) + * and need to be enabled. + * + * Some features like `$expand` are not available for advanced queries, though. + */ + queryMode?: string; user?: { /** * The filter to apply to extract users. diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts index 8e2866df65..3331e3609d 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts @@ -162,6 +162,7 @@ describe('readProviderConfigs', () => { clientId: 'clientId', clientSecret: 'clientSecret', authority: 'https://login.example.com/', + queryMode: 'advanced', user: { expand: 'manager', filter: 'accountEnabled eq true', @@ -185,6 +186,7 @@ describe('readProviderConfigs', () => { clientId: 'clientId', clientSecret: 'clientSecret', authority: 'https://login.example.com/', + queryMode: 'advanced', userExpand: 'manager', userFilter: 'accountEnabled eq true', groupExpand: 'member', diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index 2429b67c89..b8565e0d72 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -261,6 +261,15 @@ export function readProviderConfig( const groupSearch = config.getOptionalString('group.search'); const groupSelect = config.getOptionalStringArray('group.select'); + const queryMode = config.getOptionalString('queryMode'); + if ( + queryMode !== undefined && + queryMode !== 'basic' && + queryMode !== 'advanced' + ) { + throw new Error(`queryMode must be one of: basic, advanced`); + } + const userGroupMemberFilter = config.getOptionalString( 'userGroupMember.filter', ); @@ -300,6 +309,7 @@ export function readProviderConfig( groupFilter, groupSearch, groupSelect, + queryMode, userGroupMemberFilter, userGroupMemberSearch, }; From 11a03929552837210712eedcc298018cba806537 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 21:32:33 +0000 Subject: [PATCH 70/95] fix(deps): update dependency eslint-plugin-jest to v27.0.4 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8c539bdbd7..460e28fa4a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22143,8 +22143,8 @@ __metadata: linkType: hard "eslint-plugin-jest@npm:^27.0.0": - version: 27.0.2 - resolution: "eslint-plugin-jest@npm:27.0.2" + version: 27.0.4 + resolution: "eslint-plugin-jest@npm:27.0.4" dependencies: "@typescript-eslint/utils": ^5.10.0 peerDependencies: @@ -22155,7 +22155,7 @@ __metadata: optional: true jest: optional: true - checksum: 0545568a1ddd14138f08015f5f1a99e08c0d5ef5d2f14a8e66c28c1b8296a541c1075e9660f637fcb71be01f2a709991937878fc96abc760c00efc768f4598c8 + checksum: 8408d8a53bae946527ac4120865c29b3468cf58d8e5ff3b9c75c5303bb5aa451ac7e04329fc004cf6302f84431e6c6c1f2ba9009b0150d1718df58ea490ed3f5 languageName: node linkType: hard From 743bfd516afa5aaee385ce9387fa447f16da75d0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 22:13:27 +0000 Subject: [PATCH 71/95] fix(deps): update dependency jose to v4.9.3 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 460e28fa4a..20976f1797 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27528,9 +27528,9 @@ __metadata: linkType: hard "jose@npm:^4.6.0": - version: 4.9.2 - resolution: "jose@npm:4.9.2" - checksum: d3950385a6417d988c50bd8ba5407f5960624060aa8e4662c2109f1ebcc40c418e64b721a87065d8197b4aa0ddd7fb4dad5064618956dba8e74dc630916bf40f + version: 4.9.3 + resolution: "jose@npm:4.9.3" + checksum: 95865830768dcf82774d19e92dc854c5bc9dc5d9c9626a65a2974272e3aca5d2f56678611943f85802431d2d6d6f8bff9548b7cdb7578e6fe61529bd9c82e1d3 languageName: node linkType: hard From bd7c0edbfd8d0297543bfdd2dafa3f0b6e38cdb1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 23:04:13 +0000 Subject: [PATCH 72/95] fix(deps): update dependency react-virtualized-auto-sizer to v1.0.7 Signed-off-by: Renovate Bot --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 20976f1797..10e0f5e4f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34928,12 +34928,12 @@ __metadata: linkType: hard "react-virtualized-auto-sizer@npm:^1.0.6": - version: 1.0.6 - resolution: "react-virtualized-auto-sizer@npm:1.0.6" + version: 1.0.7 + resolution: "react-virtualized-auto-sizer@npm:1.0.7" peerDependencies: - react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 - react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 - checksum: 81270e9d328e9b779515f42b6aa8dea2f21097f69fc776906d6b7d31ada03706d34408a6318baf59531f180402fbf74fdb9928ab65d53442a134b7ee5ba01265 + react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc + react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc + checksum: 7f2f013c422771828c6613c7890f792aa90a033ea2b41c489c67ca2c6793eefa94d25232c1050fdf69cdd626fad9e3821c5003d45fa6fc831184cd09232023c2 languageName: node linkType: hard From beb51e25395a90a08b951f8ce4191af4244e453e Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 20 Sep 2022 10:00:37 +0200 Subject: [PATCH 73/95] chore: exit pre-release Signed-off-by: blam --- .changeset/pre.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/pre.json b/.changeset/pre.json index 028a1a665f..5644249456 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -1,5 +1,5 @@ { - "mode": "pre", + "mode": "exit", "tag": "next", "initialVersions": { "example-app": "0.2.74", From d325409a71dba9a1ed84f324a6b1c7b1ecda1153 Mon Sep 17 00:00:00 2001 From: Tim Jacomb <21194782+timja@users.noreply.github.com> Date: Tue, 20 Sep 2022 09:56:58 +0100 Subject: [PATCH 74/95] Re-order dockerfile in example backend slightly Signed-off-by: Tim Jacomb <21194782+timja@users.noreply.github.com> --- packages/backend/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/backend/Dockerfile b/packages/backend/Dockerfile index 21ff07deb4..990b4abc84 100644 --- a/packages/backend/Dockerfile +++ b/packages/backend/Dockerfile @@ -19,10 +19,8 @@ RUN apt-get update && \ yarn config set python /usr/bin/python3 # From here on we use the least-privileged `node` user to run the backend. -WORKDIR /app -RUN chown node:node /app USER node - +WORKDIR /app # This switches many Node.js dependencies to production mode. ENV NODE_ENV production From ff28494249e2748b1e27acf4020584ad71d6c543 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Tue, 9 Aug 2022 19:54:57 +0100 Subject: [PATCH 75/95] allow a custom ObjectFieldTemplate to be supplied through the ui:ObjectFieldTemplate field Signed-off-by: Paul Cowan --- .../MultistepJsonForm/MultistepJsonForm.tsx | 3 + plugins/scaffolder/src/components/Router.tsx | 25 +++++- .../TemplateEditorPage/TemplateEditor.tsx | 3 + .../TemplateEditorPage/TemplateEditorForm.tsx | 9 ++- .../TemplateEditorPage/TemplateEditorPage.tsx | 4 + .../TemplateFormPreviewer.tsx | 4 + .../components/TemplatePage/TemplatePage.tsx | 4 + .../DefaultStepFormLayout.tsx | 79 +++++++++++++++++++ .../layouts/DefaultStepFormLayout/index.tsx | 16 ++++ plugins/scaffolder/src/layouts/default.ts | 21 +++++ plugins/scaffolder/src/layouts/index.tsx | 46 +++++++++++ plugins/scaffolder/src/layouts/types.ts | 22 ++++++ .../src/next/Router/Router.test.tsx | 45 +++++++++++ plugins/scaffolder/src/next/Router/Router.tsx | 23 +++++- .../Stepper/Stepper.test.tsx | 8 +- .../TemplateWizardPage/Stepper/Stepper.tsx | 2 + .../Stepper/useTemplateSchema.test.tsx | 2 + .../TemplateWizardPage/TemplateWizardPage.tsx | 3 + 18 files changed, 315 insertions(+), 4 deletions(-) create mode 100644 plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx create mode 100644 plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/index.tsx create mode 100644 plugins/scaffolder/src/layouts/default.ts create mode 100644 plugins/scaffolder/src/layouts/index.tsx create mode 100644 plugins/scaffolder/src/layouts/types.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 43e12ae85f..97c10c34ec 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -55,6 +55,7 @@ type Props = { widgets?: FormProps['widgets']; fields?: FormProps['fields']; finishButtonLabel?: string; + layout?: FormProps['ObjectFieldTemplate']; }; export function getUiSchemasFromSteps(steps: Step[]): UiSchema[] { @@ -119,6 +120,7 @@ export const MultistepJsonForm = (props: Props) => { fields, widgets, finishButtonLabel, + layout, } = props; const [activeStep, setActiveStep] = useState(0); const [disableButtons, setDisableButtons] = useState(false); @@ -203,6 +205,7 @@ export const MultistepJsonForm = (props: Props) => {
{ ), ), ]; + + const customLayouts = useElementFilter(outlet, elements => + elements + .selectByComponentData({ + key: LAYOUTS_WRAPPER_KEY, + }) + .findComponentData({ + key: LAYOUTS_KEY, + }), + ); + + const layout = customLayouts?.[0] ?? DEFAULT_SCAFFOLDER_LAYOUT; + /** * This component can be deleted once the older routes have been deprecated. */ @@ -142,7 +161,10 @@ export const Router = (props: RouterProps) => { path={selectedTemplateRouteRef.path} element={ - + } /> @@ -159,6 +181,7 @@ export const Router = (props: RouterProps) => { } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx index cc4dd8c9a1..68ad355b61 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx @@ -16,6 +16,7 @@ import { makeStyles } from '@material-ui/core'; import React, { useState } from 'react'; import { FieldExtensionOptions } from '../../extensions'; +import { LayoutOptions } from '../../layouts'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; import { DirectoryEditorProvider } from './DirectoryEditorContext'; import { DryRunProvider } from './DryRunContext'; @@ -57,6 +58,7 @@ const useStyles = makeStyles({ export const TemplateEditor = (props: { directory: TemplateDirectoryAccess; fieldExtensions?: FieldExtensionOptions[]; + layout?: LayoutOptions; onClose?: () => void; }) => { const classes = useStyles(); @@ -77,6 +79,7 @@ export const TemplateEditor = (props: {
diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx index d802ab07dc..8b9fea6b30 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx @@ -20,6 +20,7 @@ import React, { Component, ReactNode, useMemo, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; import { FieldExtensionOptions } from '../../extensions'; +import { DEFAULT_SCAFFOLDER_LAYOUT, LayoutOptions } from '../../layouts'; import { TemplateParameterSchema } from '../../types'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from '../TemplatePage'; @@ -83,6 +84,7 @@ interface TemplateEditorFormProps { onDryRun?: (data: JsonObject) => Promise; fieldExtensions?: FieldExtensionOptions[]; + layout?: LayoutOptions; } function isJsonObject(value: JsonValue | undefined): value is JsonObject { @@ -99,6 +101,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { onDryRun, setErrorText, fieldExtensions = [], + layout = DEFAULT_SCAFFOLDER_LAYOUT, } = props; const classes = useStyles(); const apiHolder = useApiHolder(); @@ -188,6 +191,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { onReset={() => onUpdate({})} finishButtonLabel={onDryRun && 'Try It'} onFinish={onDryRun && (() => onDryRun(data))} + layout={layout.component} /> @@ -197,7 +201,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { /** A version of the TemplateEditorForm that is connected to the DirectoryEditor and DryRun contexts */ export function TemplateEditorFormDirectoryEditorDryRun( - props: Pick, + props: Pick< + TemplateEditorFormProps, + 'setErrorText' | 'fieldExtensions' | 'layout' + >, ) { const { setErrorText, fieldExtensions = [] } = props; const dryRun = useDryRun(); diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx index fce2881190..2995678248 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx @@ -23,6 +23,7 @@ import { TemplateEditorIntro } from './TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; import { FieldExtensionOptions } from '../../extensions'; +import { LayoutOptions } from '../../layouts'; type Selection = | { @@ -36,6 +37,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; customFieldExtensions?: FieldExtensionOptions[]; + layout?: LayoutOptions; } export function TemplateEditorPage(props: TemplateEditorPageProps) { @@ -48,6 +50,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) { directory={selection.directory} fieldExtensions={props.customFieldExtensions} onClose={() => setSelection(undefined)} + layout={props.layout} /> ); } else if (selection?.type === 'form') { @@ -56,6 +59,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) { defaultPreviewTemplate={props.defaultPreviewTemplate} customFieldExtensions={props.customFieldExtensions} onClose={() => setSelection(undefined)} + layout={props.layout} /> ); } else { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx index bfa7071d48..1e3758ebba 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -33,6 +33,7 @@ import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; import { FieldExtensionOptions } from '../../extensions'; +import { DEFAULT_SCAFFOLDER_LAYOUT, LayoutOptions } from '../../layouts'; import { TemplateEditorForm } from './TemplateEditorForm'; import { TemplateEditorTextArea } from './TemplateEditorTextArea'; @@ -110,10 +111,12 @@ export const TemplateFormPreviewer = ({ defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, customFieldExtensions = [], onClose, + layout = DEFAULT_SCAFFOLDER_LAYOUT, }: { defaultPreviewTemplate?: string; customFieldExtensions?: FieldExtensionOptions[]; onClose?: () => void; + layout?: LayoutOptions; }) => { const classes = useStyles(); const alertApi = useApi(alertApiRef); @@ -208,6 +211,7 @@ export const TemplateFormPreviewer = ({ data={formState} onUpdate={setFormState} setErrorText={setErrorText} + layout={layout} /> diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 03ce57136f..2d2ab3989e 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -39,6 +39,7 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { stringifyEntityRef } from '@backstage/catalog-model'; +import { DEFAULT_SCAFFOLDER_LAYOUT, LayoutOptions } from '../../layouts'; const useTemplateParameterSchema = (templateRef: string) => { const scaffolderApi = useApi(scaffolderApiRef); @@ -51,8 +52,10 @@ const useTemplateParameterSchema = (templateRef: string) => { export const TemplatePage = ({ customFieldExtensions = [], + layout = DEFAULT_SCAFFOLDER_LAYOUT, }: { customFieldExtensions?: FieldExtensionOptions[]; + layout?: LayoutOptions; }) => { const apiHolder = useApiHolder(); const secretsContext = useContext(SecretsContext); @@ -146,6 +149,7 @@ export const TemplatePage = ({ onChange={handleChange} onReset={handleFormReset} onFinish={handleCreate} + layout={layout.component} steps={schema.steps.map(step => { return { ...step, diff --git a/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx b/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx new file mode 100644 index 0000000000..871f568383 --- /dev/null +++ b/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx @@ -0,0 +1,79 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React from 'react'; +import { ObjectFieldTemplateProps, utils } from '@rjsf/core'; +import { Button, Grid } from '@material-ui/core'; + +const { canExpand } = utils; + +export const DefaultStepFormLayout = ({ + DescriptionField, + description, + TitleField, + title, + properties, + required, + disabled, + readonly, + uiSchema, + idSchema, + schema, + formData, + onAddClick, +}: ObjectFieldTemplateProps) => { + return ( + <> +

THIS IS OUR OBJECTFIELDTEMPLATE!!!!!!

+ {(uiSchema['ui:title'] || title) && ( + + )} + {description && ( + + )} + + {properties.map((element, index) => + // Remove the if the inner element is hidden as the + // itself would otherwise still take up space. + element.hidden ? ( + element.content + ) : ( + + {element.content} + + ), + )} + {canExpand(schema, uiSchema, formData) && ( + + +
diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx index 8b9fea6b30..4395f06206 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx @@ -84,7 +84,7 @@ interface TemplateEditorFormProps { onDryRun?: (data: JsonObject) => Promise; fieldExtensions?: FieldExtensionOptions[]; - layout?: LayoutOptions; + layouts?: LayoutOptions[]; } function isJsonObject(value: JsonValue | undefined): value is JsonObject { @@ -101,7 +101,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { onDryRun, setErrorText, fieldExtensions = [], - layout = DEFAULT_SCAFFOLDER_LAYOUT, + layouts = [DEFAULT_SCAFFOLDER_LAYOUT], } = props; const classes = useStyles(); const apiHolder = useApiHolder(); @@ -141,6 +141,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { } const { parameters } = rootObj; + if (!Array.isArray(parameters)) { setErrorText('Template parameters must be an array'); setSteps(undefined); @@ -191,7 +192,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { onReset={() => onUpdate({})} finishButtonLabel={onDryRun && 'Try It'} onFinish={onDryRun && (() => onDryRun(data))} - layout={layout.component} + layouts={layouts} /> @@ -203,7 +204,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { export function TemplateEditorFormDirectoryEditorDryRun( props: Pick< TemplateEditorFormProps, - 'setErrorText' | 'fieldExtensions' | 'layout' + 'setErrorText' | 'fieldExtensions' | 'layouts' >, ) { const { setErrorText, fieldExtensions = [] } = props; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx index 2995678248..b539b6403b 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx @@ -23,7 +23,7 @@ import { TemplateEditorIntro } from './TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; import { FieldExtensionOptions } from '../../extensions'; -import { LayoutOptions } from '../../layouts'; +import type { LayoutOptions } from '../../layouts'; type Selection = | { @@ -37,7 +37,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; customFieldExtensions?: FieldExtensionOptions[]; - layout?: LayoutOptions; + layouts?: LayoutOptions[]; } export function TemplateEditorPage(props: TemplateEditorPageProps) { @@ -50,7 +50,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) { directory={selection.directory} fieldExtensions={props.customFieldExtensions} onClose={() => setSelection(undefined)} - layout={props.layout} + layouts={props.layouts} /> ); } else if (selection?.type === 'form') { @@ -59,7 +59,7 @@ export function TemplateEditorPage(props: TemplateEditorPageProps) { defaultPreviewTemplate={props.defaultPreviewTemplate} customFieldExtensions={props.customFieldExtensions} onClose={() => setSelection(undefined)} - layout={props.layout} + layouts={props.layouts} /> ); } else { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx index 1e3758ebba..1cdc211865 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -111,12 +111,12 @@ export const TemplateFormPreviewer = ({ defaultPreviewTemplate = EXAMPLE_TEMPLATE_PARAMS_YAML, customFieldExtensions = [], onClose, - layout = DEFAULT_SCAFFOLDER_LAYOUT, + layouts = [DEFAULT_SCAFFOLDER_LAYOUT], }: { defaultPreviewTemplate?: string; customFieldExtensions?: FieldExtensionOptions[]; onClose?: () => void; - layout?: LayoutOptions; + layouts?: LayoutOptions[]; }) => { const classes = useStyles(); const alertApi = useApi(alertApiRef); @@ -211,7 +211,7 @@ export const TemplateFormPreviewer = ({ data={formState} onUpdate={setFormState} setErrorText={setErrorText} - layout={layout} + layouts={layouts} /> diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 2d2ab3989e..4cf3cf1841 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -52,10 +52,10 @@ const useTemplateParameterSchema = (templateRef: string) => { export const TemplatePage = ({ customFieldExtensions = [], - layout = DEFAULT_SCAFFOLDER_LAYOUT, + layouts = [DEFAULT_SCAFFOLDER_LAYOUT], }: { customFieldExtensions?: FieldExtensionOptions[]; - layout?: LayoutOptions; + layouts?: LayoutOptions[]; }) => { const apiHolder = useApiHolder(); const secretsContext = useContext(SecretsContext); @@ -149,7 +149,7 @@ export const TemplatePage = ({ onChange={handleChange} onReset={handleFormReset} onFinish={handleCreate} - layout={layout.component} + layouts={layouts} steps={schema.steps.map(step => { return { ...step, diff --git a/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx b/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx index 871f568383..b7711e59fb 100644 --- a/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx +++ b/plugins/scaffolder/src/components/layouts/DefaultStepFormLayout/DefaultStepFormLayout.tsx @@ -36,7 +36,6 @@ export const DefaultStepFormLayout = ({ }: ObjectFieldTemplateProps) => { return ( <> -

THIS IS OUR OBJECTFIELDTEMPLATE!!!!!!

{(uiSchema['ui:title'] || title) && ( = () => null; + +export function createScaffolderLayout< + TFieldReturnValue = unknown, + TInputProps = unknown, +>( options: LayoutOptions, -): Extension> { +): Extension> { return { expose() { const LayoutDataHolder: any = () => null; @@ -41,6 +44,6 @@ export const ScaffolderLayouts: React.ComponentType = (): JSX.Element | null => attachComponentData(ScaffolderLayouts, LAYOUTS_WRAPPER_KEY, true); -export type { LayoutOptions } from './types'; +export type { LayoutOptions, ObjectFieldTemplate } from './types'; export { DEFAULT_SCAFFOLDER_LAYOUT } from './default'; diff --git a/plugins/scaffolder/src/layouts/types.ts b/plugins/scaffolder/src/layouts/types.ts index 66106bda21..fb0e766a43 100644 --- a/plugins/scaffolder/src/layouts/types.ts +++ b/plugins/scaffolder/src/layouts/types.ts @@ -13,10 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ObjectFieldTemplateProps } from '@rjsf/core'; -import type { FunctionComponent } from 'react'; +import type { FormProps } from '@rjsf/core'; -export type LayoutOptions = { +export type ObjectFieldTemplate = Required< + FormProps +>['ObjectFieldTemplate']; + +export interface LayoutOptions { name: string; - component: FunctionComponent; -}; + component: ObjectFieldTemplate; +} diff --git a/plugins/scaffolder/src/next/Router/Router.test.tsx b/plugins/scaffolder/src/next/Router/Router.test.tsx index 5a47127885..d1c627de51 100644 --- a/plugins/scaffolder/src/next/Router/Router.test.tsx +++ b/plugins/scaffolder/src/next/Router/Router.test.tsx @@ -102,19 +102,17 @@ describe('Router', () => { it('should extract the custom layout and pass it through', async () => { const mockLayout = () => null; - const CustomLayout = scaffolderPlugin.provide( + const Customlayout = scaffolderPlugin.provide( createScaffolderLayout({ - name: 'customLayout', + name: 'CustomLayout', component: mockLayout, }), ); - const props = {} as ObjectFieldTemplateProps; - await renderInTestApp( - + , { routeEntries: ['/templates/default/foo'] }, @@ -124,7 +122,7 @@ describe('Router', () => { // eslint-disable-next-line no-console const [{ layout }] = mock.mock.calls[0]; - expect(layout).toEqual({ name: 'customLayout', component: mockLayout }); + expect(layout).toEqual({ name: 'CustomLayout', component: mockLayout }); }); }); }); diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 8a64c9fde9..5934206564 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -91,7 +91,13 @@ export const Router = (props: PropsWithChildren) => { }), ); - const layout = customLayouts?.[0] ?? DEFAULT_SCAFFOLDER_LAYOUT; + if ( + !customLayouts.find( + layout => layout.name === DEFAULT_SCAFFOLDER_LAYOUT.name, + ) + ) { + customLayouts.push(DEFAULT_SCAFFOLDER_LAYOUT); + } return ( @@ -111,7 +117,7 @@ export const Router = (props: PropsWithChildren) => { } diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index c87bc2ed0a..1802f8bea2 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -26,7 +26,6 @@ import { FieldValidation, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { useMemo, useState } from 'react'; import { FieldExtensionOptions } from '../../../extensions'; -import type { LayoutOptions } from '../../../layouts'; import { TemplateParameterSchema } from '../../../types'; import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from './useTemplateSchema'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 2c403f4999..e29c903e25 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -41,7 +41,7 @@ import type { LayoutOptions } from '../../layouts'; export interface TemplateWizardPageProps { customFieldExtensions: FieldExtensionOptions[]; - layout?: LayoutOptions; + layouts: LayoutOptions[]; } const useStyles = makeStyles(() => ({ @@ -115,7 +115,7 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { )} From 7fdb1fe283fa55db5ca5589d5f4977b42445a268 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Wed, 10 Aug 2022 20:16:50 +0100 Subject: [PATCH 77/95] extract ObjectFieldTemplate from uiSchema Signed-off-by: Paul Cowan --- package.json | 5 ++- packages/app/src/App.tsx | 8 +++-- .../scaffolder/customScaffolderLayouts.tsx | 27 ++++++++++++++- .../scaffolder/defaultPreviewTemplate.ts | 1 + .../MultistepJsonForm/MultistepJsonForm.tsx | 33 ++++++++++--------- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index a0de99bfad..da8f193d3a 100644 --- a/package.json +++ b/package.json @@ -93,5 +93,8 @@ "node ./scripts/check-docs-quality" ] }, - "packageManager": "yarn@3.2.3" + "packageManager": "yarn@3.2.3", + "volta": { + "node": "14.19.3" + } } diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 9969a0fcdc..7e49ad5087 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -105,7 +105,10 @@ import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow'; import { RequirePermission } from '@backstage/plugin-permission-react'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; import { PlaylistIndexPage } from '@backstage/plugin-playlist'; -import { Customlayout } from './components/scaffolder/customScaffolderLayouts'; +import { + AnotherCustomlayout, + CustomLayout, +} from './components/scaffolder/customScaffolderLayouts'; const app = createApp({ apis, @@ -222,7 +225,8 @@ const routes = ( - + + diff --git a/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx b/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx index 0fd4bed2d0..065a1ca780 100644 --- a/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderLayouts.tsx @@ -35,9 +35,34 @@ const ALayout: ObjectFieldTemplate = ({ properties, description }) => { ); }; -export const Customlayout = scaffolderPlugin.provide( +const AnotherCustomLayout: ObjectFieldTemplate = ({ + properties, + description, +}) => { + // eslint-disable-next-line no-console + return ( +
+

ANOTHER CUSTOM LAYOUT!!!!!

+
+ {properties.map(prop => ( +
{prop.content}
+ ))} +
+ {description} +
+ ); +}; + +export const CustomLayout = scaffolderPlugin.provide( createScaffolderLayout({ name: 'CustomLayout', component: ALayout, }), ); + +export const AnotherCustomlayout = scaffolderPlugin.provide( + createScaffolderLayout({ + name: 'AnotherCustomLayout', + component: AnotherCustomLayout, + }), +); diff --git a/packages/app/src/components/scaffolder/defaultPreviewTemplate.ts b/packages/app/src/components/scaffolder/defaultPreviewTemplate.ts index db0725591c..53805265ed 100644 --- a/packages/app/src/components/scaffolder/defaultPreviewTemplate.ts +++ b/packages/app/src/components/scaffolder/defaultPreviewTemplate.ts @@ -34,6 +34,7 @@ parameters: allowedKinds: - Group - title: Choose a location + ui:ObjectFieldTemplate: 'AnotherCustomLayout' required: - repoUrl properties: diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index c4384c2d04..c2050fe703 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -155,20 +155,6 @@ export const MultistepJsonForm = (props: Props) => { : filteredStep.schema.required; } - const layoutName = - filteredStep.schema['ui:ObjectFieldTemplate'] ?? - DEFAULT_SCAFFOLDER_LAYOUT.name; - - const LayoutComponent = layouts.find( - layout => layout.name === layoutName, - )?.component; - - if (!LayoutComponent) { - throw new Error(`no step layout found for ${layoutName}`); - } - - filteredStep.schema['ui:ObjectFieldTemplate'] = LayoutComponent as any; - return filteredStep; }; @@ -208,6 +194,22 @@ export const MultistepJsonForm = (props: Props) => { <> {steps.map(({ title, schema, ...formProps }, index) => { + const schemaProps = transformSchemaToProps(schema); + + const layoutName = + schemaProps.uiSchema?.['ui:ObjectFieldTemplate'] ?? + DEFAULT_SCAFFOLDER_LAYOUT.name; + + delete schemaProps.uiSchema?.['ui:ObjectFieldTemplate']; + + const LayoutComponent = layouts.find( + layout => layout.name === layoutName, + )?.component; + + if (!LayoutComponent) { + throw new Error(`no step layout found for ${layoutName}`); + } + return ( { { if (e.errors.length === 0) handleNext(); }} {...formProps} - {...transformSchemaToProps(schema)} + {...schemaProps} >